From dc59348c11accbbd74d71c9799302612c9407156 Mon Sep 17 00:00:00 2001 From: Schuyler Rosefield Date: Mon, 19 Jul 2021 18:00:52 -0400 Subject: [PATCH] Add the ability to toggle a pane's split direction - Switch from horizontal to vertical split (and vice versa) - Propogate new borders through to children. --- doc/cascadia/profiles.schema.json | 1 + .../TerminalApp/AppActionHandlers.cpp | 7 ++ src/cascadia/TerminalApp/Pane.cpp | 66 +++++++++++++++++-- src/cascadia/TerminalApp/Pane.h | 2 + src/cascadia/TerminalApp/TerminalPage.cpp | 15 +++++ src/cascadia/TerminalApp/TerminalPage.h | 1 + src/cascadia/TerminalApp/TerminalTab.cpp | 11 ++++ src/cascadia/TerminalApp/TerminalTab.h | 1 + .../TerminalSettingsModel/ActionAndArgs.cpp | 2 + .../AllShortcutActions.h | 1 + .../Resources/en-US/Resources.resw | 5 +- .../TerminalSettingsModel/defaults.json | 1 + 12 files changed, 106 insertions(+), 7 deletions(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index b7b9d2a979d..593ecb04090 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -270,6 +270,7 @@ "toggleFocusMode", "toggleFullscreen", "togglePaneZoom", + "togglePaneSplit", "toggleReadOnlyMode", "toggleShaderEffects", "wt", diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index cdc92aaf6ae..831f2f426e0 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -161,6 +161,13 @@ namespace winrt::TerminalApp::implementation } } + void TerminalPage::_HandleTogglePaneSplit(const IInspectable& /*sender*/, + const ActionEventArgs& args) + { + _TogglePaneSplit(); + args.Handled(true); + } + void TerminalPage::_HandleTogglePaneZoom(const IInspectable& /*sender*/, const ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/Pane.cpp b/src/cascadia/TerminalApp/Pane.cpp index 2dda1a442ce..0d214ab6792 100644 --- a/src/cascadia/TerminalApp/Pane.cpp +++ b/src/cascadia/TerminalApp/Pane.cpp @@ -1117,8 +1117,26 @@ void Pane::_UpdateBorders() _border.BorderThickness(ThicknessHelper::FromLengths(left, top, right, bottom)); } +// Method Description: +// - Find the borders for the leaf pane, or the shared borders for child panes. +// Arguments: +// - +// Return Value: +// - +Borders Pane::_GetCommonBorders() +{ + if (_IsLeaf()) + { + return _borders; + } + + return _firstChild->_GetCommonBorders() & _secondChild->_GetCommonBorders(); +} + // Method Description: // - Sets the row/column of our child UI elements, to match our current split type. +// - In case the split definition or parent borders were changed, this recursively +// updates the children as well. // Arguments: // - // Return Value: @@ -1134,9 +1152,8 @@ void Pane::_ApplySplitDefinitions() _secondChild->_borders = _borders | Borders::Left; _borders = Borders::None; - _UpdateBorders(); - _firstChild->_UpdateBorders(); - _secondChild->_UpdateBorders(); + _firstChild->_ApplySplitDefinitions(); + _secondChild->_ApplySplitDefinitions(); } else if (_splitState == SplitState::Horizontal) { @@ -1147,10 +1164,10 @@ void Pane::_ApplySplitDefinitions() _secondChild->_borders = _borders | Borders::Top; _borders = Borders::None; - _UpdateBorders(); - _firstChild->_UpdateBorders(); - _secondChild->_UpdateBorders(); + _firstChild->_ApplySplitDefinitions(); + _secondChild->_ApplySplitDefinitions(); } + _UpdateBorders(); } // Method Description: @@ -1411,6 +1428,43 @@ std::pair, std::shared_ptr> Pane::Split(SplitState s return _Split(splitType, splitSize, profile, control); } +// Method Description: +// - Toggle the split orientation of the currently focused pane +// Arguments: +// - +// Return Value: +// - true if a split was changed +bool Pane::TogglePaneSplit() +{ + // If we are a leaf there is no split to toggle. + if (_IsLeaf()) + { + return false; + } + + // Check if either our first or second child is the currently focused leaf. + // If they are then switch the split orientation on the current pane. + const bool firstIsFocused = _firstChild->_IsLeaf() && _firstChild->_lastActive; + const bool secondIsFocused = _secondChild->_IsLeaf() && _secondChild->_lastActive; + if (firstIsFocused || secondIsFocused) + { + // Switch the split orientation + _splitState = _splitState == SplitState::Horizontal ? SplitState::Vertical : SplitState::Horizontal; + + // then update the borders and positioning on ourselves and our children. + _borders = _GetCommonBorders(); + // Since we changed if we are using rows/columns, make sure we remove the old definitions + _root.ColumnDefinitions().Clear(); + _root.RowDefinitions().Clear(); + _CreateRowColDefinitions(); + _ApplySplitDefinitions(); + + return true; + } + + return _firstChild->TogglePaneSplit() || _secondChild->TogglePaneSplit(); +} + // Method Description: // - Converts an "automatic" split type into either Vertical or Horizontal, // based upon the current dimensions of the Pane. diff --git a/src/cascadia/TerminalApp/Pane.h b/src/cascadia/TerminalApp/Pane.h index 6e7f801b787..fffa9378e17 100644 --- a/src/cascadia/TerminalApp/Pane.h +++ b/src/cascadia/TerminalApp/Pane.h @@ -61,6 +61,7 @@ class Pane : public std::enable_shared_from_this const float splitSize, const GUID& profile, const winrt::Microsoft::Terminal::Control::TermControl& control); + bool TogglePaneSplit(); float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const; std::optional PreCalculateAutoSplit(const std::shared_ptr target, const winrt::Windows::Foundation::Size parentSize) const; @@ -135,6 +136,7 @@ class Pane : public std::enable_shared_from_this void _ApplySplitDefinitions(); void _SetupEntranceAnimation(); void _UpdateBorders(); + Borders _GetCommonBorders(); bool _Resize(const winrt::Microsoft::Terminal::Settings::Model::ResizeDirection& direction); bool _NavigateFocus(const winrt::Microsoft::Terminal::Settings::Model::FocusDirection& direction); diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index d1efbcac4e4..679dde13840 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1290,6 +1290,21 @@ namespace winrt::TerminalApp::implementation CATCH_LOG(); } + // Method Description: + // - Switches the split orientation of the currently focused pane. + // Arguments: + // - + // Return Value: + // - + void TerminalPage::_TogglePaneSplit() + { + if (const auto terminalTab{ _GetFocusedTabImpl() }) + { + _UnZoomIfNeeded(); + terminalTab->TogglePaneSplit(); + } + } + // Method Description: // - Attempt to move a separator between panes, as to resize each child on // either size of the separator. See Pane::ResizePane for details. diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 6d7370b9acd..148eb0cf6f4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -254,6 +254,7 @@ namespace winrt::TerminalApp::implementation const float splitSize = 0.5f, const Microsoft::Terminal::Settings::Model::NewTerminalArgs& newTerminalArgs = nullptr); void _ResizePane(const Microsoft::Terminal::Settings::Model::ResizeDirection& direction); + void _TogglePaneSplit(); void _ScrollPage(ScrollDirection scrollDirection); void _ScrollToBufferEdge(ScrollDirection scrollDirection); diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp index 4a09839407a..b06c51ad940 100644 --- a/src/cascadia/TerminalApp/TerminalTab.cpp +++ b/src/cascadia/TerminalApp/TerminalTab.cpp @@ -440,6 +440,16 @@ namespace winrt::TerminalApp::implementation _UpdateActivePane(second); } + // Method Description: + // - Find the currently active pane, and then switch the split direction of + // its parent. E.g. switch from Horizontal to Vertical. + // Return Value: + // - + void TerminalTab::TogglePaneSplit() + { + _rootPane->TogglePaneSplit(); + } + // Method Description: // - See Pane::CalcSnappedDimension float TerminalTab::CalcSnappedDimension(const bool widthOrHeight, const float dimension) const @@ -1188,6 +1198,7 @@ namespace winrt::TerminalApp::implementation EnterZoom(); } } + void TerminalTab::EnterZoom() { _zoomedPane = _activePane; diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h index 7167f74a67c..5a6233bd0d7 100644 --- a/src/cascadia/TerminalApp/TerminalTab.h +++ b/src/cascadia/TerminalApp/TerminalTab.h @@ -38,6 +38,7 @@ namespace winrt::TerminalApp::implementation const GUID& profile, winrt::Microsoft::Terminal::Control::TermControl& control); + void TogglePaneSplit(); winrt::fire_and_forget UpdateIcon(const winrt::hstring iconPath); winrt::fire_and_forget HideIcon(const bool hide); diff --git a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp index 430980a6c95..04682bee2f4 100644 --- a/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp +++ b/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp @@ -48,6 +48,7 @@ static constexpr std::string_view ToggleCommandPaletteKey{ "commandPalette" }; static constexpr std::string_view ToggleFocusModeKey{ "toggleFocusMode" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; static constexpr std::string_view TogglePaneZoomKey{ "togglePaneZoom" }; +static constexpr std::string_view TogglePaneSplitKey{ "togglePaneSplit" }; static constexpr std::string_view LegacyToggleRetroEffectKey{ "toggleRetroEffect" }; static constexpr std::string_view ToggleShaderEffectsKey{ "toggleShaderEffects" }; static constexpr std::string_view MoveTabKey{ "moveTab" }; @@ -347,6 +348,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { ShortcutAction::ToggleFocusMode, RS_(L"ToggleFocusModeCommandKey") }, { ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") }, { ShortcutAction::TogglePaneZoom, RS_(L"TogglePaneZoomCommandKey") }, + { ShortcutAction::TogglePaneSplit, RS_(L"TogglePaneSplitCommandKey") }, { ShortcutAction::ToggleShaderEffects, RS_(L"ToggleShaderEffectsCommandKey") }, { ShortcutAction::MoveTab, L"" }, // Intentionally omitted, must be generated by GenerateName { ShortcutAction::BreakIntoDebugger, RS_(L"BreakIntoDebuggerCommandKey") }, diff --git a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h index cc3559037ba..ef11d5c01aa 100644 --- a/src/cascadia/TerminalSettingsModel/AllShortcutActions.h +++ b/src/cascadia/TerminalSettingsModel/AllShortcutActions.h @@ -36,6 +36,7 @@ ON_ALL_ACTIONS(PrevTab) \ ON_ALL_ACTIONS(SendInput) \ ON_ALL_ACTIONS(SplitPane) \ + ON_ALL_ACTIONS(TogglePaneSplit) \ ON_ALL_ACTIONS(TogglePaneZoom) \ ON_ALL_ACTIONS(SwitchToTab) \ ON_ALL_ACTIONS(AdjustFontSize) \ diff --git a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw index d44ecc5ddbf..142295fe6a6 100644 --- a/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalSettingsModel/Resources/en-US/Resources.resw @@ -374,6 +374,9 @@ Toggle fullscreen + + Toggle pane split + Toggle pane zoom @@ -417,4 +420,4 @@ Windows Console Host Name describing the usage of the classic windows console as the terminal UI. (`conhost.exe`) - \ No newline at end of file + diff --git a/src/cascadia/TerminalSettingsModel/defaults.json b/src/cascadia/TerminalSettingsModel/defaults.json index 84f52f287b2..20d12e8796d 100644 --- a/src/cascadia/TerminalSettingsModel/defaults.json +++ b/src/cascadia/TerminalSettingsModel/defaults.json @@ -345,6 +345,7 @@ { "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" }, { "command": { "action": "moveFocus", "direction": "previous" }, "keys": "ctrl+alt+left" }, { "command": "togglePaneZoom" }, + { "command": "togglePaneSplit" }, { "command": "toggleReadOnlyMode" }, // Clipboard Integration