Skip to content

Commit

Permalink
Make ITab an unsealed runtimeclass (#8053)
Browse files Browse the repository at this point in the history
`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
  • Loading branch information
carlos-zamora authored Oct 29, 2020
1 parent 18ac211 commit 81ca24b
Show file tree
Hide file tree
Showing 15 changed files with 259 additions and 309 deletions.
1 change: 1 addition & 0 deletions .github/actions/spell-check/dictionary/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ oaidl
ocidl
otms
OUTLINETEXTMETRICW
overridable
PAGESCROLL
RETURNCMD
rfind
Expand Down
140 changes: 11 additions & 129 deletions src/cascadia/TerminalApp/SettingsTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,6 @@ namespace winrt::TerminalApp::implementation
_CreateIcon();
}

// Method Description:
// - Initializes a TabViewItem for this Tab instance.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SettingsTab::_MakeTabViewItem()
{
TabViewItem(::winrt::MUX::Controls::TabViewItem{});
Title(RS_(L"SettingsTab"));
TabViewItem().Header(winrt::box_value(Title()));
}

// Method Description:
// - Focus the settings UI
// Arguments:
Expand All @@ -56,13 +43,21 @@ namespace winrt::TerminalApp::implementation

if (_focusState != FocusState::Unfocused)
{
Content().Focus(focusState);
Content().as<WUX::Controls::Page>().Focus(focusState);
}
}

WUX::FocusState SettingsTab::FocusState() const noexcept
// Method Description:
// - Initializes a TabViewItem for this Tab instance.
// Arguments:
// - <none>
// Return Value:
// - <none>
void SettingsTab::_MakeTabViewItem()
{
return _focusState;
TabViewItem(::winrt::MUX::Controls::TabViewItem{});
Title(RS_(L"SettingsTab"));
TabViewItem().Header(winrt::box_value(Title()));
}

// Method Description:
Expand Down Expand Up @@ -90,117 +85,4 @@ namespace winrt::TerminalApp::implementation
SwitchToTabCommand().Icon(glyph);
}
}

// Method Description:
// - Prepares this tab for being removed from the UI hierarchy
void SettingsTab::Shutdown()
{
// TODO: Does/Will the settings UI need some shutdown procedures?
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 SettingsTab::_CreateContextMenu()
{
auto weakThis{ get_weak() };

// Close
Controls::MenuFlyoutItem closeTabMenuItem;
Controls::FontIcon closeSymbol;
closeSymbol.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
closeSymbol.Glyph(L"\xE8BB");

closeTabMenuItem.Click([weakThis](auto&&, auto&&) {
if (auto tab{ weakThis.get() })
{
tab->_ClosedHandlers(nullptr, nullptr);
}
});
closeTabMenuItem.Text(RS_(L"TabClose"));
closeTabMenuItem.Icon(closeSymbol);

// Build the menu
Controls::MenuFlyout newTabFlyout;
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 SettingsTab::_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 SettingsTab::_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 SettingsTab::_CloseTabsAfter()
{
CloseTabsAfterArgs args{ _TabViewIndex };
ActionAndArgs closeTabsAfter{ ShortcutAction::CloseTabsAfter, args };

_dispatch.DoAction(closeTabsAfter);
}

void SettingsTab::_CloseOtherTabs()
{
CloseOtherTabsArgs args{ _TabViewIndex };
ActionAndArgs closeOtherTabs{ ShortcutAction::CloseOtherTabs, args };

_dispatch.DoAction(closeOtherTabs);
}

void SettingsTab::SetDispatch(const winrt::TerminalApp::ShortcutActionDispatch& dispatch)
{
_dispatch = dispatch;
}
}
33 changes: 3 additions & 30 deletions src/cascadia/TerminalApp/SettingsTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,23 @@ Author(s):
--*/

#pragma once
#include "TabBase.h"
#include "SettingsTab.g.h"
#include <winrt/TerminalApp.h>
#include <winrt/Microsoft.Terminal.Settings.Editor.h>
#include "../../cascadia/inc/cppwinrt_utils.h"

namespace winrt::TerminalApp::implementation
{
struct SettingsTab : SettingsTabT<SettingsTab>
struct SettingsTab : SettingsTabT<SettingsTab, TabBase>
{
public:
SettingsTab(winrt::Microsoft::Terminal::Settings::Editor::MainPage settingsUI);
void Focus(winrt::Windows::UI::Xaml::FocusState focusState);
winrt::Windows::UI::Xaml::FocusState FocusState() const noexcept;

void Shutdown();

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);

GETSET_PROPERTY(winrt::hstring, Title);
GETSET_PROPERTY(winrt::hstring, Icon);
GETSET_PROPERTY(winrt::Microsoft::Terminal::Settings::Model::Command, SwitchToTabCommand, nullptr);
GETSET_PROPERTY(winrt::Microsoft::UI::Xaml::Controls::TabViewItem, TabViewItem, nullptr);
GETSET_PROPERTY(winrt::Windows::UI::Xaml::Controls::Page, Content, nullptr);

// 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);
void Focus(winrt::Windows::UI::Xaml::FocusState focusState) override;

private:
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::TerminalApp::ShortcutActionDispatch _dispatch;

void _MakeTabViewItem();
void _CreateContextMenu();
winrt::Windows::UI::Xaml::Controls::MenuFlyoutSubItem _CreateCloseSubMenu();
void _EnableCloseMenuItems();
winrt::fire_and_forget _CreateIcon();
void _CloseTabsAfter();
void _CloseOtherTabs();
};
}
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/SettingsTab.idl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import "ITab.idl";
import "TabBase.idl";

namespace TerminalApp
{
[default_interface] runtimeclass SettingsTab : ITab
[default_interface] runtimeclass SettingsTab : TabBase
{
}
}
18 changes: 0 additions & 18 deletions src/cascadia/TerminalApp/Tab.idl

This file was deleted.

Loading

0 comments on commit 81ca24b

Please sign in to comment.