Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a togglePaneZoom action for zooming a pane #6989

Merged
merged 11 commits into from
Aug 7, 2020
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/ActionAndArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ static constexpr std::string_view ScrolldownpageKey{ "scrollDownPage" };
static constexpr std::string_view SwitchToTabKey{ "switchToTab" };
static constexpr std::string_view OpenSettingsKey{ "openSettings" }; // TODO GH#2557: Add args for OpenSettings
static constexpr std::string_view SplitPaneKey{ "splitPane" };
static constexpr std::string_view TogglePaneZoomKey{ "togglePaneZoom" };
static constexpr std::string_view ResizePaneKey{ "resizePane" };
static constexpr std::string_view MoveFocusKey{ "moveFocus" };
static constexpr std::string_view FindKey{ "find" };
Expand Down Expand Up @@ -85,6 +86,7 @@ namespace winrt::TerminalApp::implementation
{ ToggleFullscreenKey, ShortcutAction::ToggleFullscreen },
{ ToggleAlwaysOnTopKey, ShortcutAction::ToggleAlwaysOnTop },
{ SplitPaneKey, ShortcutAction::SplitPane },
{ TogglePaneZoomKey, ShortcutAction::TogglePaneZoom },
{ SetTabColorKey, ShortcutAction::SetTabColor },
{ OpenTabColorPickerKey, ShortcutAction::OpenTabColorPicker },
{ UnboundKey, ShortcutAction::Invalid },
Expand Down Expand Up @@ -267,6 +269,7 @@ namespace winrt::TerminalApp::implementation
{ ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") },
{ ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") },
{ ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") },
{ ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") },
{ ShortcutAction::Invalid, L"" },
{ ShortcutAction::Find, RS_(L"FindCommandKey") },
{ ShortcutAction::SetTabColor, RS_(L"ResetTabColorCommandKey") },
Expand Down
20 changes: 20 additions & 0 deletions src/cascadia/TerminalApp/AppActionHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ namespace winrt::TerminalApp::implementation
}
}

void TerminalPage::_HandleTogglePaneZoom(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& args)
{
auto activeTab = _GetFocusedTab();
if (activeTab)
{
// First thing's first, remove the current content from the UI
// tree. This is important, because we might be leaving zoom, and if
// a pane is zoomed, then it's currently in the UI tree, and should
// be removed before it's re-added in Pane::Restore
_tabContent.Children().Clear();

activeTab->ToggleZoom();

// Update the selected tab, to trigger us to re-add the tab's GetRootElement to the UI tree
_UpdatedSelectedTab(_tabView.SelectedIndex());
}
args.Handled(true);
}

void TerminalPage::_HandleScrollUpPage(const IInspectable& /*sender*/,
const TerminalApp::ActionEventArgs& args)
{
Expand Down
102 changes: 90 additions & 12 deletions src/cascadia/TerminalApp/Pane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,21 +841,29 @@ void Pane::_UpdateBorders()
double top = 0, bottom = 0, left = 0, right = 0;

Thickness newBorders{ 0 };
if (WI_IsFlagSet(_borders, Borders::Top))
if (_zoomed)
{
top = PaneBorderSize;
// When the pane is zoomed, manually show all the borders around the window.
top = bottom = right = left = PaneBorderSize;
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
}
if (WI_IsFlagSet(_borders, Borders::Bottom))
{
bottom = PaneBorderSize;
}
if (WI_IsFlagSet(_borders, Borders::Left))
{
left = PaneBorderSize;
}
if (WI_IsFlagSet(_borders, Borders::Right))
else
{
right = PaneBorderSize;
if (WI_IsFlagSet(_borders, Borders::Top))
{
top = PaneBorderSize;
}
if (WI_IsFlagSet(_borders, Borders::Bottom))
{
bottom = PaneBorderSize;
}
if (WI_IsFlagSet(_borders, Borders::Left))
{
left = PaneBorderSize;
}
if (WI_IsFlagSet(_borders, Borders::Right))
{
right = PaneBorderSize;
}
}
_border.BorderThickness(ThicknessHelper::FromLengths(left, top, right, bottom));
}
Expand Down Expand Up @@ -1173,6 +1181,76 @@ std::pair<std::shared_ptr<Pane>, std::shared_ptr<Pane>> Pane::_Split(SplitState
return { _firstChild, _secondChild };
}

// Method Description:
// - Recursively attempt to "zoom" the given pane. When the pane is zoomed, it
// won't be displayed as part of the tab tree, instead it'll take up the full
// content of the tab. When we find the given pane, we'll need to remove it
// from the UI tree, so that the caller can re-add it. We'll also set some
// internal state, so the pane can display all of its borders.
// Arguments:
// - zoomedPane: This is the pane which we're attempting to zoom on.
// Return Value:
// - <none>
void Pane::Maximize(std::shared_ptr<Pane> zoomedPane)
{
if (_IsLeaf())
{
_zoomed = (zoomedPane == shared_from_this());
_UpdateBorders();
}
else
{
if (zoomedPane == _firstChild || zoomedPane == _secondChild)
{
// When we're zooming the pane, we'll need to remove it from our UI
// tree. Easy way: just remove both children. We'll re-attach both
// when we un-zoom.
_root.Children().Clear();
}

// Always recurse into both children. If the (un)zoomed pane was one of
// our direct children, we'll still want to update it's borders.
_firstChild->Maximize(zoomedPane);
_secondChild->Maximize(zoomedPane);
}
}

// Method Description:
// - Recursively attempt to "un-zoom" the given pane. This does the opposite of
// Pane::Maximize. When we find the given pane, we should return the pane to our
// UI tree. We'll also clear the internal state, so the pane can display its
// borders correctly.
// - The caller should make sure to have removed the zoomed pane from the UI
// tree _before_ calling this.
// Arguments:
// - zoomedPane: This is the pane which we're attempting to un-zoom.
// Return Value:
// - <none>
void Pane::Restore(std::shared_ptr<Pane> zoomedPane)
{
if (_IsLeaf())
{
_zoomed = false;
_UpdateBorders();
}
else
{
if (zoomedPane == _firstChild || zoomedPane == _secondChild)
{
// When we're un-zooming the pane, we'll need to re-add it to our UI
// tree where it originally belonged. easy way: just re-add both.
_root.Children().Clear();
_root.Children().Append(_firstChild->GetRootElement());
_root.Children().Append(_secondChild->GetRootElement());
}

// Always recurse into both children. If the (un)zoomed pane was one of
// our direct children, we'll still want to update it's borders.
_firstChild->Restore(zoomedPane);
_secondChild->Restore(zoomedPane);
}
}

// Method Description:
// - Gets the size in pixels of each of our children, given the full size they
// should fill. Since these children own their own separators (borders), this
Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/TerminalApp/Pane.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class Pane : public std::enable_shared_from_this<Pane>

int GetLeafPaneCount() const noexcept;

void Maximize(std::shared_ptr<Pane> zoomedPane);
void Restore(std::shared_ptr<Pane> zoomedPane);

WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
DECLARE_EVENT(GotFocus, _GotFocusHandlers, winrt::delegate<std::shared_ptr<Pane>>);

Expand Down Expand Up @@ -103,6 +106,8 @@ class Pane : public std::enable_shared_from_this<Pane>

Borders _borders{ Borders::None };

bool _zoomed{ false };

bool _IsLeaf() const noexcept;
bool _HasFocusedChild() const noexcept;
void _SetupChildCloseHandlers();
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@
<data name="SplitPaneCommandKey" xml:space="preserve">
<value>Split pane</value>
</data>
<data name="TogglePaneZoomCommandKey" xml:space="preserve">
<value>Toggle pane zoom</value>
</data>
<data name="NewWindowCommandKey" xml:space="preserve">
<value>New window</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ namespace winrt::TerminalApp::implementation
break;
}

case ShortcutAction::TogglePaneZoom:
{
_TogglePaneZoomHandlers(*this, *eventArgs);
break;
}

case ShortcutAction::SwitchToTab:
{
_SwitchToTabHandlers(*this, *eventArgs);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(NextTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(PrevTab, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(SplitPane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(TogglePaneZoom, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(AdjustFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(ResetFontSize, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
TYPED_EVENT(ScrollUp, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/ShortcutActionDispatch.idl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace TerminalApp
SplitVertical,
SplitHorizontal,
SplitPane,
TogglePaneZoom,
SwitchToTab,
AdjustFontSize,
ResetFontSize,
Expand Down Expand Up @@ -67,6 +68,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> NextTab;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> PrevTab;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> SplitPane;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> TogglePaneZoom;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> AdjustFontSize;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ResetFontSize;
event Windows.Foundation.TypedEventHandler<ShortcutActionDispatch, ActionEventArgs> ScrollUp;
Expand Down
75 changes: 72 additions & 3 deletions src/cascadia/TerminalApp/Tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,14 @@ namespace winrt::TerminalApp::implementation
// - The UIElement acting as root of the Tab's root pane.
UIElement Tab::GetRootElement()
{
return _rootPane->GetRootElement();
if (_zoomedPane)
{
return _zoomedPane->GetRootElement();
}
else
{
return _rootPane->GetRootElement();
}
}

// Method Description:
Expand Down Expand Up @@ -587,8 +594,28 @@ namespace winrt::TerminalApp::implementation

if (!_inRename)
{
// If we're not currently in the process of renaming the tab, then just set the tab's text to whatever our active title is.
_tabViewItem.Header(winrt::box_value(tabText));
if (_zoomedPane)
{
Controls::StackPanel sp;
sp.Orientation(Controls::Orientation::Horizontal);
Controls::FontIcon ico;
ico.FontFamily(Media::FontFamily{ L"Segoe MDL2 Assets" });
ico.Glyph(L"\xE8A3"); // "ZoomIn", a magnifying glass with a '+' in it.
ico.FontSize(12);
ico.Margin(ThicknessHelper::FromLengths(0, 0, 8, 0));
sp.Children().Append(ico);
Controls::TextBlock tb;
tb.Text(tabText);
sp.Children().Append(tb);

_tabViewItem.Header(sp);
}
else
{
// If we're not currently in the process of renaming the tab,
// then just set the tab's text to whatever our active title is.
_tabViewItem.Header(winrt::box_value(tabText));
}
}
else
{
Expand Down Expand Up @@ -879,6 +906,48 @@ namespace winrt::TerminalApp::implementation
{
return _rootPane->PreCalculateCanSplit(_activePane, splitType, availableSpace).value_or(false);
}

// Method Description:
// - Toggle our zoom state.
// * If we're not zoomed, then zoom the active pane, making it take the
// full size of the tab. We'll achieve this by changing our response to
// Tab::GetRootElement, so that it'll return the zoomed pane only.
// * If we're currently zoomed on a pane, un-zoom that pane.
// Arguments:
// - <none>
// Return Value:
// - <none>
void Tab::ToggleZoom()
{
if (_zoomedPane)
{
ExitZoom();
}
else
{
EnterZoom();
}
}
void Tab::EnterZoom()
{
_zoomedPane = _activePane;
_rootPane->Maximize(_zoomedPane);
// Update the tab header to show the magnifying glass
_UpdateTabHeader();
}
void Tab::ExitZoom()
{
_rootPane->Restore(_zoomedPane);
_zoomedPane = nullptr;
// Update the tab header to hide the magnifying glass
_UpdateTabHeader();
}

bool Tab::IsZoomed()
{
return _zoomedPane != nullptr;
}

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
6 changes: 6 additions & 0 deletions src/cascadia/TerminalApp/Tab.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ namespace winrt::TerminalApp::implementation
void ResetTabColor();
void ActivateColorPicker();

void ToggleZoom();
bool IsZoomed();
void EnterZoom();
void ExitZoom();

WINRT_CALLBACK(Closed, winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>);
WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);
DECLARE_EVENT(ActivePaneChanged, _ActivePaneChangedHandlers, winrt::delegate<>);
Expand All @@ -73,6 +78,7 @@ namespace winrt::TerminalApp::implementation
private:
std::shared_ptr<Pane> _rootPane{ nullptr };
std::shared_ptr<Pane> _activePane{ nullptr };
std::shared_ptr<Pane> _zoomedPane{ nullptr };
winrt::hstring _lastIconPath{};
winrt::TerminalApp::ColorPickupFlyout _tabColorPickup{};
std::optional<winrt::Windows::UI::Color> _tabColor{};
Expand Down
Loading