Skip to content

Commit

Permalink
Refactor the SettingsTab to be a pane (#16172)
Browse files Browse the repository at this point in the history
... 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
  • Loading branch information
zadjii-msft committed Apr 3, 2024
1 parent 2bcbe6b commit 67ae9f6
Show file tree
Hide file tree
Showing 25 changed files with 440 additions and 363 deletions.
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Expand Up @@ -1418,7 +1418,7 @@ namespace winrt::TerminalApp::implementation
args.Handled(true);
}

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

const auto resultPane = std::make_shared<Pane>(*scratchPane);
_SplitPane(_GetFocusedTabImpl(), SplitDirection::Automatic, 0.5f, resultPane);
_SplitPane(_senderOrFocusedTab(sender), SplitDirection::Automatic, 0.5f, resultPane);
args.Handled(true);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/IPaneContent.idl
Expand Up @@ -19,13 +19,17 @@ namespace TerminalApp
interface IPaneContent
{
Windows.UI.Xaml.FrameworkElement GetRoot();
void UpdateSettings(Microsoft.Terminal.Settings.Model.CascadiaSettings settings);

Windows.Foundation.Size MinimumSize { get; };

String Title { get; };
UInt64 TaskbarState { get; };
UInt64 TaskbarProgress { get; };
Boolean ReadOnly { get; };
String Icon { get; };
Windows.Foundation.IReference<Windows.UI.Color> TabColor { get; };
Windows.UI.Xaml.Media.Brush BackgroundBrush { get; };

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

Expand Down
55 changes: 41 additions & 14 deletions src/cascadia/TerminalApp/Pane.cpp
Expand Up @@ -1075,6 +1075,29 @@ TermControl Pane::GetLastFocusedTerminalControl()
return GetTerminalControl();
}

IPaneContent Pane::GetLastFocusedContent()
{
if (!_IsLeaf())
{
if (_lastActive)
{
auto pane = shared_from_this();
while (const auto p = pane->_parentChildPath.lock())
{
if (p->_IsLeaf())
{
return p->_content;
}
pane = p;
}
// We didn't find our child somehow, they might have closed under us.
}
return _firstChild->GetLastFocusedContent();
}

return _content;
}

// Method Description:
// - Gets the TermControl of this pane. If this Pane is not a leaf this will
// return the nullptr;
Expand Down Expand Up @@ -1215,7 +1238,10 @@ void Pane::UpdateVisuals()
void Pane::_Focus()
{
GotFocus.raise(shared_from_this(), FocusState::Programmatic);
_content.Focus(FocusState::Programmatic);
if (const auto& lastContent{ GetLastFocusedContent() })
{
lastContent.Focus(FocusState::Programmatic);
}
}

// Method Description:
Expand Down Expand Up @@ -1254,20 +1280,21 @@ void Pane::_FocusFirstChild()
}
}

// Method Description:
// - Updates the settings of this pane, presuming that it is a leaf.
// Arguments:
// - settings: The new TerminalSettings to apply to any matching controls
// - profile: The profile from which these settings originated.
// Return Value:
// - <none>
void Pane::UpdateSettings(const TerminalSettingsCreateResult& settings, const Profile& profile)
void Pane::UpdateSettings(const CascadiaSettings& settings, const winrt::TerminalApp::TerminalSettingsCache& cache)
{
assert(_IsLeaf());

if (const auto& terminalPane{ _getTerminalContent() })
if (_content)
{
return terminalPane.UpdateSettings(settings, profile);
// We need to do a bit more work here for terminal
// panes. They need to know about the profile that was used for
// them, and about the focused/unfocused settings.
if (const auto& terminalPaneContent{ _content.try_as<TerminalPaneContent>() })
{
terminalPaneContent.UpdateTerminalSettings(cache);
}
else
{
_content.UpdateSettings(settings);
}
}
}

Expand Down Expand Up @@ -1893,7 +1920,7 @@ void Pane::_SetupEntranceAnimation()
auto child = isFirstChild ? _firstChild : _secondChild;
auto childGrid = child->_root;
// If we are splitting a parent pane this may be null
auto control = child->_content.GetRoot();
auto control = child->_content ? child->_content.GetRoot() : nullptr;
// Build up our animation:
// * it'll take as long as our duration (200ms)
// * it'll change the value of our property from 0 to secondSize
Expand Down
4 changes: 2 additions & 2 deletions src/cascadia/TerminalApp/Pane.h
Expand Up @@ -73,6 +73,7 @@ class Pane : public std::enable_shared_from_this<Pane>

std::shared_ptr<Pane> GetActivePane();
winrt::Microsoft::Terminal::Control::TermControl GetLastFocusedTerminalControl();
winrt::TerminalApp::IPaneContent GetLastFocusedContent();
winrt::Microsoft::Terminal::Control::TermControl GetTerminalControl() const;
winrt::Microsoft::Terminal::Settings::Model::Profile GetFocusedProfile();
bool IsConnectionClosed() const;
Expand Down Expand Up @@ -107,8 +108,7 @@ class Pane : public std::enable_shared_from_this<Pane>
BuildStartupState BuildStartupActions(uint32_t currentId, uint32_t nextId, winrt::TerminalApp::BuildStartupKind kind);
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetTerminalArgsForPane(winrt::TerminalApp::BuildStartupKind kind) const;

void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::TerminalSettingsCreateResult& settings,
const winrt::Microsoft::Terminal::Settings::Model::Profile& profile);
void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings, const winrt::TerminalApp::TerminalSettingsCache& cache);
bool ResizePane(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction);
std::shared_ptr<Pane> NavigateDirection(const std::shared_ptr<Pane> sourcePane,
const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction,
Expand Down
16 changes: 16 additions & 0 deletions src/cascadia/TerminalApp/ScratchpadContent.cpp
Expand Up @@ -26,6 +26,11 @@ namespace winrt::TerminalApp::implementation
_root.Children().Append(_box);
}

void ScratchpadContent::UpdateSettings(const CascadiaSettings& /*settings*/)
{
// Nothing to do.
}

winrt::Windows::UI::Xaml::FrameworkElement ScratchpadContent::GetRoot()
{
return _root;
Expand All @@ -47,4 +52,15 @@ namespace winrt::TerminalApp::implementation
{
return nullptr;
}

winrt::hstring ScratchpadContent::Icon() const
{
static constexpr std::wstring_view glyph{ L"\xe70b" }; // QuickNote
return winrt::hstring{ glyph };
}

winrt::Windows::UI::Xaml::Media::Brush ScratchpadContent::BackgroundBrush()
{
return _root.Background();
}
}
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/ScratchpadContent.h
Expand Up @@ -13,6 +13,8 @@ namespace winrt::TerminalApp::implementation

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

void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);

winrt::Windows::Foundation::Size MinimumSize();

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

til::typed_event<> ConnectionStateChanged;
til::typed_event<IPaneContent> CloseRequested;
Expand Down
84 changes: 84 additions & 0 deletions src/cascadia/TerminalApp/SettingsPaneContent.cpp
@@ -0,0 +1,84 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#include "pch.h"
#include "SettingsPaneContent.h"
#include "Utils.h"

using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Microsoft::Terminal::Settings::Model;

#define ASSERT_UI_THREAD() assert(_sui.Dispatcher().HasThreadAccess())

namespace winrt::TerminalApp::implementation
{
SettingsPaneContent::SettingsPaneContent(CascadiaSettings settings)
{
_sui = winrt::Microsoft::Terminal::Settings::Editor::MainPage{ settings };

// Stash away the current requested theme of the app. We'll need that in
// _BackgroundBrush() to do a theme-aware resource lookup
_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
}

void SettingsPaneContent::UpdateSettings(const CascadiaSettings& settings)
{
ASSERT_UI_THREAD();
_sui.UpdateSettings(settings);

_requestedTheme = settings.GlobalSettings().CurrentTheme().RequestedTheme();
}

winrt::Windows::UI::Xaml::FrameworkElement SettingsPaneContent::GetRoot()
{
return _sui;
}
winrt::Windows::Foundation::Size SettingsPaneContent::MinimumSize()
{
return { 1, 1 };
}
void SettingsPaneContent::Focus(winrt::Windows::UI::Xaml::FocusState reason)
{
if (reason != FocusState::Unfocused)
{
_sui.as<Controls::Page>().Focus(reason);
}
}
void SettingsPaneContent::Close()
{
CloseRequested.raise(*this, nullptr);
}

NewTerminalArgs SettingsPaneContent::GetNewTerminalArgs(const BuildStartupKind /*kind*/) const
{
// For now, we're doing a terrible thing in TerminalTab itself to
// generate an OpenSettings action manually, without asking for the pane
// structure.
return nullptr;
}

winrt::hstring SettingsPaneContent::Icon() const
{
// This is the Setting icon (looks like a gear)
static constexpr std::wstring_view glyph{ L"\xE713" };
return winrt::hstring{ glyph };
}

Windows::Foundation::IReference<winrt::Windows::UI::Color> SettingsPaneContent::TabColor() const noexcept
{
return nullptr;
}

winrt::Windows::UI::Xaml::Media::Brush SettingsPaneContent::BackgroundBrush()
{
// Look up the color we should use for the settings tab item from our
// resources. This should only be used for when "terminalBackground" is
// requested.
static const auto key = winrt::box_value(L"SettingsUiTabBrush");
// You can't just do a Application::Current().Resources().TryLookup
// lookup, cause the app theme never changes! Do the hacky version
// instead.
return ThemeLookup(Application::Current().Resources(), _requestedTheme, key).try_as<winrt::Windows::UI::Xaml::Media::Brush>();
}
}
46 changes: 46 additions & 0 deletions src/cascadia/TerminalApp/SettingsPaneContent.h
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once
#include "winrt/TerminalApp.h"
#include <LibraryResources.h>

namespace winrt::TerminalApp::implementation
{
class SettingsPaneContent : public winrt::implements<SettingsPaneContent, IPaneContent>
{
public:
SettingsPaneContent(winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings settings);

void UpdateSettings(const winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings& settings);

winrt::Windows::UI::Xaml::FrameworkElement GetRoot();
winrt::Microsoft::Terminal::Settings::Editor::MainPage SettingsUI() { return _sui; }

winrt::Windows::Foundation::Size MinimumSize();
void Focus(winrt::Windows::UI::Xaml::FocusState reason = winrt::Windows::UI::Xaml::FocusState::Programmatic);
void Close();
winrt::Microsoft::Terminal::Settings::Model::NewTerminalArgs GetNewTerminalArgs(const BuildStartupKind kind) const;

winrt::hstring Title() { return RS_(L"SettingsTab"); }
uint64_t TaskbarState() { return 0; }
uint64_t TaskbarProgress() { return 0; }
bool ReadOnly() { return false; }
winrt::hstring Icon() const;
Windows::Foundation::IReference<winrt::Windows::UI::Color> TabColor() const noexcept;
winrt::Windows::UI::Xaml::Media::Brush BackgroundBrush();

til::typed_event<> ConnectionStateChanged;
til::typed_event<IPaneContent> CloseRequested;
til::typed_event<IPaneContent, winrt::TerminalApp::BellEventArgs> BellRequested;
til::typed_event<IPaneContent> TitleChanged;
til::typed_event<IPaneContent> TabColorChanged;
til::typed_event<IPaneContent> TaskbarProgressChanged;
til::typed_event<IPaneContent> ReadOnlyChanged;
til::typed_event<IPaneContent> FocusRequested;

private:
winrt::Microsoft::Terminal::Settings::Editor::MainPage _sui{ nullptr };
winrt::Windows::UI::Xaml::ElementTheme _requestedTheme;
};
}

0 comments on commit 67ae9f6

Please sign in to comment.