Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
|
|
#include <LibraryResources.h>
|
|
|
|
#include "TabBase.h"
|
|
|
|
#include "TabBase.g.cpp"
|
|
|
|
|
|
|
|
using namespace winrt;
|
|
|
|
using namespace winrt::Windows::UI::Xaml;
|
|
|
|
using namespace winrt::Windows::UI::Core;
|
2021-03-17 21:47:24 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal::Control;
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
|
|
|
using namespace winrt::Windows::System;
|
|
|
|
|
|
|
|
namespace winrt
|
|
|
|
{
|
|
|
|
namespace MUX = Microsoft::UI::Xaml;
|
|
|
|
namespace WUX = Windows::UI::Xaml;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace winrt::TerminalApp::implementation
|
|
|
|
{
|
|
|
|
WUX::FocusState TabBase::FocusState() const noexcept
|
|
|
|
{
|
|
|
|
return _focusState;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Prepares this tab for being removed from the UI hierarchy
|
|
|
|
void TabBase::Shutdown()
|
|
|
|
{
|
|
|
|
Content(nullptr);
|
|
|
|
_ClosedHandlers(nullptr, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Creates a context menu attached to the tab.
|
|
|
|
// Currently contains elements allowing the user to close the selected tab
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TabBase::_CreateContextMenu()
|
|
|
|
{
|
|
|
|
auto weakThis{ get_weak() };
|
|
|
|
|
|
|
|
// Build the menu
|
In specific scenarios, focus the active control (#10048)
A redo of #6290. That PR was overkill. In that one, we'd toss focus back to the active control any time that the tab view item got focus. That's maybe not the _best_ solution.
Instead, this PR is precision strikes. We're re-using a lot of what we already have from #9260.
* When the context menu is closed, yeet focus to the control.
* When the renamer is dismissed, yeet focus to the control.
* When the TabViewItem is tapped (meaning no one else handled it), yeet focus to the control.
### checklist
* [x] I work here
* [ ] This is UI so it doesn't have tests
* [x] Closes #3609
* [x] Closes #5750
* [x] Closes #6680
### scenarios:
* [x] focus the window by clicking on the tab -> Control is focused.
* [x] Open the color picker with the context menu, can move the focus inside the picker with the arrow keys.
* [x] Dismiss the picker with esc -> Control is focused.
* [x] Dismiss the picker with enter -> Control is focused.
* [x] Dismiss the renamer with esc -> Control is focused.
* [x] Dismiss the renamer with enter -> Control is focused.
* [x] Dismiss the context menu with esc -> Control is focused.
* [x] Start renaming, then click on the tab -> Rename is committed, Control is focused.
* [x] Start renaming, then click on the text box -> focus is still in the text box
2021-05-12 01:55:49 +02:00
|
|
|
Controls::MenuFlyout contextMenuFlyout;
|
|
|
|
// GH#5750 - When the context menu is dismissed with ESC, toss the focus
|
|
|
|
// back to our control.
|
|
|
|
contextMenuFlyout.Closed([weakThis](auto&&, auto&&) {
|
|
|
|
if (auto tab{ weakThis.get() })
|
|
|
|
{
|
|
|
|
tab->_RequestFocusActiveControlHandlers();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
_AppendCloseMenuItems(contextMenuFlyout);
|
|
|
|
TabViewItem().ContextFlyout(contextMenuFlyout);
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
2021-04-21 12:53:19 +02:00
|
|
|
// - Append the close menu items to the context menu flyout
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
// Arguments:
|
2021-04-21 12:53:19 +02:00
|
|
|
// - flyout - the menu flyout to which the close items must be appended
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
// Return Value:
|
2021-04-21 12:53:19 +02:00
|
|
|
// - <none>
|
|
|
|
void TabBase::_AppendCloseMenuItems(winrt::Windows::UI::Xaml::Controls::MenuFlyout flyout)
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
{
|
|
|
|
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"));
|
|
|
|
|
2021-04-21 12:53:19 +02:00
|
|
|
// Close
|
|
|
|
Controls::MenuFlyoutItem closeTabMenuItem;
|
|
|
|
Controls::FontIcon closeSymbol;
|
|
|
|
closeSymbol.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
|
|
|
|
closeSymbol.Glyph(L"\xE711");
|
|
|
|
|
|
|
|
closeTabMenuItem.Click([weakThis](auto&&, auto&&) {
|
|
|
|
if (auto tab{ weakThis.get() })
|
|
|
|
{
|
|
|
|
tab->_CloseRequestedHandlers(nullptr, nullptr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
closeTabMenuItem.Text(RS_(L"TabClose"));
|
|
|
|
closeTabMenuItem.Icon(closeSymbol);
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
|
2021-04-21 12:53:19 +02:00
|
|
|
// GH#8238 append the close menu items to the flyout itself until crash in XAML is fixed
|
|
|
|
//Controls::MenuFlyoutSubItem closeSubMenu;
|
|
|
|
//closeSubMenu.Text(RS_(L"TabCloseSubMenu"));
|
|
|
|
//closeSubMenu.Items().Append(_closeTabsAfterMenuItem);
|
|
|
|
//closeSubMenu.Items().Append(_closeOtherTabsMenuItem);
|
|
|
|
//flyout.Items().Append(closeSubMenu);
|
|
|
|
flyout.Items().Append(_closeTabsAfterMenuItem);
|
|
|
|
flyout.Items().Append(_closeOtherTabsMenuItem);
|
|
|
|
flyout.Items().Append(closeTabMenuItem);
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Enable the Close menu items based on tab index and total number of tabs
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TabBase::_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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TabBase::_CloseTabsAfter()
|
|
|
|
{
|
|
|
|
CloseTabsAfterArgs args{ _TabViewIndex };
|
|
|
|
ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args };
|
|
|
|
|
|
|
|
_dispatch.DoAction(closeTabsAfter);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TabBase::_CloseOtherTabs()
|
|
|
|
{
|
|
|
|
CloseOtherTabsArgs args{ _TabViewIndex };
|
|
|
|
ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args };
|
|
|
|
|
|
|
|
_dispatch.DoAction(closeOtherTabs);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TabBase::UpdateTabViewIndex(const uint32_t idx, const uint32_t numTabs)
|
|
|
|
{
|
|
|
|
TabViewIndex(idx);
|
|
|
|
TabViewNumTabs(numTabs);
|
|
|
|
_EnableCloseMenuItems();
|
2021-01-19 12:44:04 +01:00
|
|
|
_UpdateSwitchToTabKeyChord();
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void TabBase::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch)
|
|
|
|
{
|
|
|
|
_dispatch = dispatch;
|
|
|
|
}
|
2021-01-19 12:44:04 +01:00
|
|
|
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
void TabBase::SetActionMap(const Microsoft::Terminal::Settings::Model::IActionMapView& actionMap)
|
2021-01-19 12:44:04 +01:00
|
|
|
{
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
_actionMap = actionMap;
|
2021-01-19 12:44:04 +01:00
|
|
|
_UpdateSwitchToTabKeyChord();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Sets the key chord resulting in switch to the current tab.
|
|
|
|
// Updates tool tip if required
|
|
|
|
// Arguments:
|
|
|
|
// - keyChord - string representation of the key chord that switches to the current tab
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
winrt::fire_and_forget TabBase::_UpdateSwitchToTabKeyChord()
|
|
|
|
{
|
Introduce ActionMap to Terminal Settings Model (#9621)
This entirely removes `KeyMapping` from the settings model, and builds on the work done in #9543 to consolidate all actions (key bindings and commands) into a unified data structure (`ActionMap`).
## References
#9428 - Spec
#6900 - Actions page
Closes #7441
## Detailed Description of the Pull Request / Additional comments
The important thing here is to remember that we're shifting our philosophy of how to interact/represent actions. Prior to this, the actions arrays in the JSON would be deserialized twice: once for key bindings, and again for commands. By thinking of every entry in the relevant JSON as a `Command`, we can remove a lot of the context switching between working with a key binding vs a command palette item.
#9543 allows us to make that shift. Given the work in that PR, we can now deserialize all of the relevant information from each JSON action item. This allows us to simplify `ActionMap::FromJson` to simply iterate over each JSON action item, deserialize it, and add it to our `ActionMap`.
Internally, our `ActionMap` operates as discussed in #9428 by maintaining a `_KeyMap` that points to an action ID, and using that action ID to retrieve the `Command` from the `_ActionMap`. Adding actions to the `ActionMap` automatically accounts for name/key-chord collisions. A `NameMap` can be constructed when requested; this is for the Command Palette.
Querying the `ActionMap` is fairly straightforward. Helper functions were needed to be able to distinguish an explicit unbinding vs the command not being found in the current layer. Internally, we store explicitly unbound names/key-chords as `ShortcutAction::Invalid` commands. However, we return `nullptr` when a query points to an unbound command. This is done to hide this complexity away from any caller.
The command palette still needs special handling for nested and iterable commands. Thankfully, the expansion of iterable commands is performed on an `IMapView`, so we can just expose `NameMap` as a consolidation of `ActionMap`'s `NameMap` with its parents. The same can be said for exposing key chords in nested commands.
## Validation Steps Performed
All local tests pass.
2021-05-05 06:50:13 +02:00
|
|
|
const auto keyChord = _actionMap ? _actionMap.GetKeyBindingForAction(ShortcutAction::SwitchToTab, SwitchToTabArgs{ _TabViewIndex }) : nullptr;
|
2021-01-19 12:44:04 +01:00
|
|
|
const auto keyChordText = keyChord ? KeyChordSerialization::ToString(keyChord) : L"";
|
|
|
|
|
|
|
|
if (_keyChord == keyChordText)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_keyChord = keyChordText;
|
|
|
|
|
|
|
|
auto weakThis{ get_weak() };
|
|
|
|
|
|
|
|
co_await winrt::resume_foreground(TabViewItem().Dispatcher());
|
|
|
|
|
|
|
|
if (auto tab{ weakThis.get() })
|
|
|
|
{
|
|
|
|
_UpdateToolTip();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-25 23:50:21 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Creates a text for the title run in the tool tip by returning tab title
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - The value to populate in the title run of the tool tip
|
|
|
|
winrt::hstring TabBase::_CreateToolTipTitle()
|
|
|
|
{
|
|
|
|
return _Title;
|
|
|
|
}
|
|
|
|
|
2021-01-19 12:44:04 +01:00
|
|
|
// Method Description:
|
|
|
|
// - Sets tab tool tip to a concatenation of title and key chord
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TabBase::_UpdateToolTip()
|
|
|
|
{
|
|
|
|
auto titleRun = WUX::Documents::Run();
|
2021-01-25 23:50:21 +01:00
|
|
|
titleRun.Text(_CreateToolTipTitle());
|
2021-01-19 12:44:04 +01:00
|
|
|
|
|
|
|
auto textBlock = WUX::Controls::TextBlock{};
|
2021-04-21 17:40:17 +02:00
|
|
|
textBlock.TextWrapping(WUX::TextWrapping::Wrap);
|
2021-01-19 12:44:04 +01:00
|
|
|
textBlock.TextAlignment(WUX::TextAlignment::Center);
|
|
|
|
textBlock.Inlines().Append(titleRun);
|
|
|
|
|
|
|
|
if (!_keyChord.empty())
|
|
|
|
{
|
|
|
|
auto keyChordRun = WUX::Documents::Run();
|
|
|
|
keyChordRun.Text(_keyChord);
|
|
|
|
keyChordRun.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic);
|
|
|
|
textBlock.Inlines().Append(WUX::Documents::LineBreak{});
|
|
|
|
textBlock.Inlines().Append(keyChordRun);
|
|
|
|
}
|
|
|
|
|
|
|
|
WUX::Controls::ToolTip toolTip{};
|
|
|
|
toolTip.Content(textBlock);
|
|
|
|
WUX::Controls::ToolTipService::SetToolTip(TabViewItem(), toolTip);
|
|
|
|
}
|
In specific scenarios, focus the active control (#10048)
A redo of #6290. That PR was overkill. In that one, we'd toss focus back to the active control any time that the tab view item got focus. That's maybe not the _best_ solution.
Instead, this PR is precision strikes. We're re-using a lot of what we already have from #9260.
* When the context menu is closed, yeet focus to the control.
* When the renamer is dismissed, yeet focus to the control.
* When the TabViewItem is tapped (meaning no one else handled it), yeet focus to the control.
### checklist
* [x] I work here
* [ ] This is UI so it doesn't have tests
* [x] Closes #3609
* [x] Closes #5750
* [x] Closes #6680
### scenarios:
* [x] focus the window by clicking on the tab -> Control is focused.
* [x] Open the color picker with the context menu, can move the focus inside the picker with the arrow keys.
* [x] Dismiss the picker with esc -> Control is focused.
* [x] Dismiss the picker with enter -> Control is focused.
* [x] Dismiss the renamer with esc -> Control is focused.
* [x] Dismiss the renamer with enter -> Control is focused.
* [x] Dismiss the context menu with esc -> Control is focused.
* [x] Start renaming, then click on the tab -> Rename is committed, Control is focused.
* [x] Start renaming, then click on the text box -> focus is still in the text box
2021-05-12 01:55:49 +02:00
|
|
|
|
|
|
|
// Method Description:
|
|
|
|
// - Initializes a TabViewItem for this Tab instance.
|
|
|
|
// Arguments:
|
|
|
|
// - <none>
|
|
|
|
// Return Value:
|
|
|
|
// - <none>
|
|
|
|
void TabBase::_MakeTabViewItem()
|
|
|
|
{
|
|
|
|
TabViewItem(::winrt::MUX::Controls::TabViewItem{});
|
|
|
|
|
|
|
|
// GH#3609 If the tab was tapped, and no one else was around to handle
|
|
|
|
// it, then ask our parent to toss focus into the active control.
|
|
|
|
TabViewItem().Tapped([weakThis{ get_weak() }](auto&&, auto&&) {
|
|
|
|
if (auto tab{ weakThis.get() })
|
|
|
|
{
|
|
|
|
tab->_RequestFocusActiveControlHandlers();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
Make Tab an unsealed runtimeclass (and rename it to TabBase) (#8153)
In preparation for the Settings UI, we needed to make some changes to
Tab to abstract out shared, common functionality between different types
of tab. This is the result of that work. All code references to the
settings have been removed or reverted.
Contains changes from #8053, #7802.
The messages below only make sense in the context of the Settings UI,
which this pull request does not bring in. They do, however, provide
valuable information.
From #7802 (@leonMSFT):
> This PR's goal was to add an option to the `OpenSettings` keybinding to
> open the Settings UI in a tab. In order to implement that, a couple of
> changes had to be made to `Tab`, specifically:
>
> - Introduce a tab interface named `ITab`
> - Create/Rename two new Tab classes that implement `ITab` called
> `SettingsTab` and `TerminalTab`
>
From #8053:
> `TerminalTab` and `SettingsTab` share some implementation details. The
> close submenu introduced in #7728 is a good example of functionality
> that is consistent across all tabs. This PR transforms `ITab` from an
> interface, into an [unsealed runtime class] to de-duplicate some
> functionality. Most of the logic from `SettingsTab` was moved there
> because I expect the default behavior of a tab to resemble the
> `SettingsTab` over a `TerminalTab`.
>
> ## References
> Verified that Close submenu work was transferred over (#7728, #7961, #8010).
>
> ## Validation Steps Performed
> Check close submenu on first/last tab when multiple tabs are open.
>
> Closes #7969
>
> [unsealed runtime class]: https://docs.microsoft.com/en-us/uwp/midl-3/intro#base-classes
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
Co-authored-by: Leon Liang <lelian@microsoft.com>
Co-authored-by: Carlos Zamora <carlos.zamora@microsoft.com>
2020-11-04 19:15:05 +01:00
|
|
|
}
|