Skip to content

Commit 67ae9f6

Browse files
authored
Refactor the SettingsTab to be a pane (#16172)
... technically. We still won't let it actually _be_ a pane, but now it acts like one. It's hosted in a `SettingsPaneContent`. There's no more `SettingsTab`. It totally _can_ be in a pane (but don't?) ## Validation Steps Performed * Still opens the settings * Only opens a single settings tab, or re-activates the existing one * Session restores! * Updates the title of the tab appropriately * I previously _did_ use the scratchpad action to open the settings in a pane, and that worked. ## Related PRs * #16170 * #16171 * #16172 <-- you are here * #16895 Refs #997 Closes #8452
1 parent 2bcbe6b commit 67ae9f6

25 files changed

+440
-363
lines changed

src/cascadia/TerminalApp/AppActionHandlers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ namespace winrt::TerminalApp::implementation
14181418
args.Handled(true);
14191419
}
14201420

1421-
void TerminalPage::_HandleOpenScratchpad(const IInspectable& /*sender*/,
1421+
void TerminalPage::_HandleOpenScratchpad(const IInspectable& sender,
14221422
const ActionEventArgs& args)
14231423
{
14241424
if (Feature_ScratchpadPane::IsEnabled())
@@ -1431,7 +1431,7 @@ namespace winrt::TerminalApp::implementation
14311431
scratchPane->GetRoot().KeyDown({ this, &TerminalPage::_KeyDownHandler });
14321432

14331433
const auto resultPane = std::make_shared<Pane>(*scratchPane);
1434-
_SplitPane(_GetFocusedTabImpl(), SplitDirection::Automatic, 0.5f, resultPane);
1434+
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
14351435
args.Handled(true);
14361436
}
14371437
}

src/cascadia/TerminalApp/IPaneContent.idl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ namespace TerminalApp
1919
interface IPaneContent
2020
{
2121
Windows.UI.Xaml.FrameworkElement GetRoot();
22+
void UpdateSettings(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);
2223

2324
Windows.Foundation.Size MinimumSize { get; };
2425

2526
String Title { get; };
2627
UInt64 TaskbarState { get; };
2728
UInt64 TaskbarProgress { get; };
2829
Boolean ReadOnly { get; };
30+
String Icon { get; };
31+
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
32+
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };
2933

3034
Microsoft.Terminal.Settings.Model.NewTerminalArgs GetNewTerminalArgs(BuildStartupKind kind);
3135

src/cascadia/TerminalApp/Pane.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,29 @@ TermControl Pane::GetLastFocusedTerminalControl()
10751075
return GetTerminalControl();
10761076
}
10771077

1078+
IPaneContent Pane::GetLastFocusedContent()
1079+
{
1080+
if (!_IsLeaf())
1081+
{
1082+
if (_lastActive)
1083+
{
1084+
auto pane = shared_from_this();
1085+
while (const auto p = pane->_parentChildPath.lock())
1086+
{
1087+
if (p->_IsLeaf())
1088+
{
1089+
return p->_content;
1090+
}
1091+
pane = p;
1092+
}
1093+
// We didn't find our child somehow, they might have closed under us.
1094+
}
1095+
return _firstChild->GetLastFocusedContent();
1096+
}
1097+
1098+
return _content;
1099+
}
1100+
10781101
// Method Description:
10791102
// - Gets the TermControl of this pane. If this Pane is not a leaf this will
10801103
// return the nullptr;
@@ -1215,7 +1238,10 @@ void Pane::UpdateVisuals()
12151238
void Pane::_Focus()
12161239
{
12171240
GotFocus.raise(shared_from_this(), FocusState::Programmatic);
1218-
_content.Focus(FocusState::Programmatic);
1241+
if (const auto& lastContent{ GetLastFocusedContent() })
1242+
{
1243+
lastContent.Focus(FocusState::Programmatic);
1244+
}
12191245
}
12201246

12211247
// Method Description:
@@ -1254,20 +1280,21 @@ void Pane::_FocusFirstChild()
12541280
}
12551281
}
12561282

1257-
// Method Description:
1258-
// - Updates the settings of this pane, presuming that it is a leaf.
1259-
// Arguments:
1260-
// - settings: The new TerminalSettings to apply to any matching controls
1261-
// - profile: The profile from which these settings originated.
1262-
// Return Value:
1263-
// - <none>
1264-
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
1283+
void Pane::UpdateSettings(const CascadiaSettings& settings, const winrt::TerminalApp::TerminalSettingsCache& cache)
12651284
{
1266-
assert(_IsLeaf());
1267-
1268-
if (const auto& terminalPane{ _getTerminalContent() })
1285+
if (_content)
12691286
{
1270-
return terminalPane.UpdateSettings(settings, profile);
1287+
// We need to do a bit more work here for terminal
1288+
// panes. They need to know about the profile that was used for
1289+
// them, and about the focused/unfocused settings.
1290+
if (const auto& terminalPaneContent{ _content.try_as<TerminalPaneContent>() })
1291+
{
1292+
terminalPaneContent.UpdateTerminalSettings(cache);
1293+
}
1294+
else
1295+
{
1296+
_content.UpdateSettings(settings);
1297+
}
12711298
}
12721299
}
12731300

@@ -1893,7 +1920,7 @@ void Pane::_SetupEntranceAnimation()
18931920
auto child = isFirstChild ? _firstChild : _secondChild;
18941921
auto childGrid = child->_root;
18951922
// If we are splitting a parent pane this may be null
1896-
auto control = child->_content.GetRoot();
1923+
auto control = child->_content ? child->_content.GetRoot() : nullptr;
18971924
// Build up our animation:
18981925
// * it'll take as long as our duration (200ms)
18991926
// * it'll change the value of our property from 0 to secondSize

src/cascadia/TerminalApp/Pane.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class Pane : public std::enable_shared_from_this<Pane>
7373

7474
std::shared_ptr<Pane> GetActivePane();
7575
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
76+
winrt::TerminalApp::IPaneContent GetLastFocusedContent();
7677
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
7778
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
7879
bool IsConnectionClosed() const;
@@ -107,8 +108,7 @@ class Pane : public std::enable_shared_from_this<Pane>
107108
BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, winrt::TerminalApp::BuildStartupKind kind);
108109
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const;
109110

110-
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
111-
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
111+
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings, const winrt::TerminalApp::TerminalSettingsCache& cache);
112112
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
113113
std::shared_ptr<Pane> NavigateDirection(const std::shared_ptr<Pane> sourcePane,
114114
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,

src/cascadia/TerminalApp/ScratchpadContent.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ namespace winrt::TerminalApp::implementation
2626
_root.Children().Append(_box);
2727
}
2828

29+
void ScratchpadContent::UpdateSettings(const CascadiaSettings& /*settings*/)
30+
{
31+
// Nothing to do.
32+
}
33+
2934
winrt::Windows::UI::Xaml::FrameworkElement ScratchpadContent::GetRoot()
3035
{
3136
return _root;
@@ -47,4 +52,15 @@ namespace winrt::TerminalApp::implementation
4752
{
4853
return nullptr;
4954
}
55+
56+
winrt::hstring ScratchpadContent::Icon() const
57+
{
58+
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
59+
return winrt::hstring{ glyph };
60+
}
61+
62+
winrt::Windows::UI::Xaml::Media::Brush ScratchpadContent::BackgroundBrush()
63+
{
64+
return _root.Background();
65+
}
5066
}

src/cascadia/TerminalApp/ScratchpadContent.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ namespace winrt::TerminalApp::implementation
1313

1414
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
1515

16+
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
17+
1618
winrt::Windows::Foundation::Size MinimumSize();
1719

1820
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
@@ -23,6 +25,9 @@ namespace winrt::TerminalApp::implementation
2325
uint64_t TaskbarState() { return 0; }
2426
uint64_t TaskbarProgress() { return 0; }
2527
bool ReadOnly() { return false; }
28+
winrt::hstring Icon() const;
29+
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept { return nullptr; }
30+
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
2631

2732
til::typed_event<> ConnectionStateChanged;
2833
til::typed_event<IPaneContent> CloseRequested;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#include "pch.h"
5+
#include "SettingsPaneContent.h"
6+
#include "Utils.h"
7+
8+
using namespace winrt::Windows::Foundation;
9+
using namespace winrt::Windows::UI::Xaml;
10+
using namespace winrt::Microsoft::Terminal::Settings::Model;
11+
12+
#define ASSERT_UI_THREAD() assert(_sui.Dispatcher().HasThreadAccess())
13+
14+
namespace winrt::TerminalApp::implementation
15+
{
16+
SettingsPaneContent::SettingsPaneContent(CascadiaSettings settings)
17+
{
18+
_sui = winrt::Microsoft::Terminal::Settings::Editor::MainPage{ settings };
19+
20+
// Stash away the current requested theme of the app. We'll need that in
21+
// _BackgroundBrush() to do a theme-aware resource lookup
22+
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
23+
}
24+
25+
void SettingsPaneContent::UpdateSettings(const CascadiaSettings& settings)
26+
{
27+
ASSERT_UI_THREAD();
28+
_sui.UpdateSettings(settings);
29+
30+
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
31+
}
32+
33+
winrt::Windows::UI::Xaml::FrameworkElement SettingsPaneContent::GetRoot()
34+
{
35+
return _sui;
36+
}
37+
winrt::Windows::Foundation::Size SettingsPaneContent::MinimumSize()
38+
{
39+
return { 1, 1 };
40+
}
41+
void SettingsPaneContent::Focus(winrt::Windows::UI::Xaml::FocusState reason)
42+
{
43+
if (reason != FocusState::Unfocused)
44+
{
45+
_sui.as<Controls::Page>().Focus(reason);
46+
}
47+
}
48+
void SettingsPaneContent::Close()
49+
{
50+
CloseRequested.raise(*this, nullptr);
51+
}
52+
53+
NewTerminalArgs SettingsPaneContent::GetNewTerminalArgs(const BuildStartupKind /*kind*/) const
54+
{
55+
// For now, we're doing a terrible thing in TerminalTab itself to
56+
// generate an OpenSettings action manually, without asking for the pane
57+
// structure.
58+
return nullptr;
59+
}
60+
61+
winrt::hstring SettingsPaneContent::Icon() const
62+
{
63+
// This is the Setting icon (looks like a gear)
64+
static constexpr std::wstring_view glyph{ L"\xE713" };
65+
return winrt::hstring{ glyph };
66+
}
67+
68+
Windows::Foundation::IReference<winrt::Windows::UI::Color> SettingsPaneContent::TabColor() const noexcept
69+
{
70+
return nullptr;
71+
}
72+
73+
winrt::Windows::UI::Xaml::Media::Brush SettingsPaneContent::BackgroundBrush()
74+
{
75+
// Look up the color we should use for the settings tab item from our
76+
// resources. This should only be used for when "terminalBackground" is
77+
// requested.
78+
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
79+
// You can't just do a Application::Current().Resources().TryLookup
80+
// lookup, cause the app theme never changes! Do the hacky version
81+
// instead.
82+
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
83+
}
84+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#pragma once
5+
#include "winrt/TerminalApp.h"
6+
#include <LibraryResources.h>
7+
8+
namespace winrt::TerminalApp::implementation
9+
{
10+
class SettingsPaneContent : public winrt::implements<SettingsPaneContent, IPaneContent>
11+
{
12+
public:
13+
SettingsPaneContent(winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings settings);
14+
15+
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);
16+
17+
winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
18+
winrt::Microsoft::Terminal::Settings::Editor::MainPage SettingsUI() { return _sui; }
19+
20+
winrt::Windows::Foundation::Size MinimumSize();
21+
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
22+
void Close();
23+
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(const BuildStartupKind kind) const;
24+
25+
winrt::hstring Title() { return RS_(L"SettingsTab"); }
26+
uint64_t TaskbarState() { return 0; }
27+
uint64_t TaskbarProgress() { return 0; }
28+
bool ReadOnly() { return false; }
29+
winrt::hstring Icon() const;
30+
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
31+
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();
32+
33+
til::typed_event<> ConnectionStateChanged;
34+
til::typed_event<IPaneContent> CloseRequested;
35+
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
36+
til::typed_event<IPaneContent> TitleChanged;
37+
til::typed_event<IPaneContent> TabColorChanged;
38+
til::typed_event<IPaneContent> TaskbarProgressChanged;
39+
til::typed_event<IPaneContent> ReadOnlyChanged;
40+
til::typed_event<IPaneContent> FocusRequested;
41+
42+
private:
43+
winrt::Microsoft::Terminal::Settings::Editor::MainPage _sui{ nullptr };
44+
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
45+
};
46+
}

0 commit comments

Comments
 (0)