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

Updated pane context menu #18126

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0ac796f
added split up/down/left/right context menus
dmitrykok Oct 29, 2024
d920a70
added build win x64 release script
dmitrykok Oct 29, 2024
7e41e64
moved split up/down/left/right context menus as submenu
dmitrykok Oct 30, 2024
58cbe3a
added to split with profile to up/down/left/right context menu, added…
dmitrykok Oct 30, 2024
6e2529b
fix startup directory for split with profile to up/down/left/right co…
dmitrykok Oct 30, 2024
c953b44
Merge branch 'microsoft:main' into main
dmitrykok Oct 30, 2024
ef25c63
update win x64 release build script
dmitrykok Oct 30, 2024
f900ea5
added translations for available languages
dmitrykok Oct 30, 2024
a57aff8
Update settings.json
dmitrykok Oct 30, 2024
ae838ec
Update settings.json
dmitrykok Oct 30, 2024
ab01742
removed newly added file
dmitrykok Oct 30, 2024
4ab861c
put back comments removed by mistake in TerminalPage.cpp, revert the …
dmitrykok Oct 30, 2024
409783a
revert .vscode/settings.json
dmitrykok Oct 30, 2024
e21c0b7
fixed Resources.resw SwapPaneText resource
dmitrykok Nov 1, 2024
12aad74
Update TerminalPage.cpp
dmitrykok Nov 1, 2024
f682222
the split pane entries exists twice on the second level, add a 'dupli…
dmitrykok Nov 2, 2024
3bcaa51
add visible with a separation line between the 'duplicate' entry and …
dmitrykok Nov 7, 2024
2c303d0
Update TerminalPage.cpp
dmitrykok Nov 7, 2024
0cabf20
fixed pane context menu separators
dmitrykok Nov 7, 2024
e6f0d6a
Update TerminalPage.cpp
dmitrykok Nov 7, 2024
526e0a9
fixed pane context menu separators, and formatting
dmitrykok Nov 7, 2024
52dbc03
Merge branch 'main' of github.com:dmitrykok/terminal
dmitrykok Nov 7, 2024
82aa44a
fixed formatting
dmitrykok Nov 7, 2024
bf1e135
update swap menu, show only available options
dmitrykok Nov 8, 2024
1d5a220
add find to context menu even if there is no selection
dmitrykok Nov 8, 2024
54c9c60
Update src/cascadia/TerminalApp/Resources/en-US/Resources.resw
dmitrykok Dec 11, 2024
9a936f4
cache the value of focusedProfile.Name() and focusedProfile.Icon(), c…
dmitrykok Dec 11, 2024
8cf4ad6
No need to manually override the value from the profile, with the val…
dmitrykok Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/cascadia/TerminalApp/Resources/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,42 @@
<data name="SplitPaneText" xml:space="preserve">
<value>Split pane</value>
</data>
<data name="SplitPaneDownText" xml:space="preserve">
<value>Split pane down</value>
</data>
<data name="SplitPaneRightText" xml:space="preserve">
<value>Split pane right</value>
</data>
<data name="SplitPaneUpText" xml:space="preserve">
<value>Split pane up</value>
</data>
<data name="SplitPaneLeftText" xml:space="preserve">
<value>Split pane left</value>
</data>
<data name="SplitPaneDuplicateText" xml:space="preserve">
<value>Duplicate</value>
</data>
<data name="SwapPaneText" xml:space="preserve">
<value>Swap pane</value>
</data>
<data name="SwapPaneDownText" xml:space="preserve">
<value>Swap pane down</value>
</data>
<data name="SwapPaneRightText" xml:space="preserve">
<value>Swap pane right</value>
</data>
<data name="SwapPaneUpText" xml:space="preserve">
<value>Swap pane up</value>
</data>
<data name="SwapPaneLeftText" xml:space="preserve">
<value>Swap pane left</value>
</data>
<data name="TogglePaneZoomText" xml:space="preserve">
<value>Toggle pane zoom</value>
</data>
<data name="CloseOtherPanesText" xml:space="preserve">
<value>Close other panes</value>
</data>
<data name="SearchWebText" xml:space="preserve">
<value>Web search</value>
</data>
Expand Down
126 changes: 116 additions & 10 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5034,9 +5034,10 @@ namespace winrt::TerminalApp::implementation
};
};

auto makeItem = [&menu, &makeCallback](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& action) {
auto makeItem = [&makeCallback](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& action,
auto& targetMenu) {
AppBarButton button{};

if (!icon.empty())
Expand All @@ -5048,34 +5049,139 @@ namespace winrt::TerminalApp::implementation

button.Label(label);
button.Click(makeCallback(action));
menu.SecondaryCommands().Append(button);
targetMenu.SecondaryCommands().Append(button);
};

auto makeMenuItem = [](const winrt::hstring& label,
const winrt::hstring& icon,
const auto& subMenu,
auto& targetMenu) {
AppBarButton button{};

if (!icon.empty())
{
auto iconElement = UI::IconPathConverter::IconWUX(icon);
Automation::AutomationProperties::SetAccessibilityView(iconElement, Automation::Peers::AccessibilityView::Raw);
button.Icon(iconElement);
}

button.Label(label);
button.Flyout(subMenu);
targetMenu.SecondaryCommands().Append(button);
};

const auto focusedProfile = _GetFocusedTabImpl()->GetFocusedProfile();
auto separatorItem = AppBarSeparator{};
auto activeProfiles = _settings.ActiveProfiles();
auto activeProfileCount = gsl::narrow_cast<int>(activeProfiles.Size());
MUX::Controls::CommandBarFlyout splitPaneDownMenu{};
MUX::Controls::CommandBarFlyout splitPaneUpMenu{};
MUX::Controls::CommandBarFlyout splitPaneRightMenu{};
MUX::Controls::CommandBarFlyout splitPaneLeftMenu{};

// Wire up each item to the action that should be performed. By actually
// connecting these to actions, we ensure the implementation is
// consistent. This also leaves room for customizing this menu with
// actions in the future.

makeItem(RS_(L"SplitPaneText"), L"\xF246", ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate } });
makeItem(RS_(L"DuplicateTabText"), L"\xF5ED", ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr });
makeItem(RS_(L"DuplicateTabText"), L"\xF5ED", ActionAndArgs{ ShortcutAction::DuplicateTab, nullptr }, menu);

const auto focusedProfileName = focusedProfile.Name();
const auto focusedProfileIcon = focusedProfile.Icon();

makeItem(RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Down, .5, nullptr } }, splitPaneDownMenu);
makeItem(RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Up, .5, nullptr } }, splitPaneUpMenu);
makeItem(RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Right, .5, nullptr } }, splitPaneRightMenu);
makeItem(RS_(L"SplitPaneDuplicateText") + L" " + focusedProfileName, focusedProfileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Duplicate, SplitDirection::Left, .5, nullptr } }, splitPaneLeftMenu);

// add menu separator
const auto separatorDownItem = AppBarSeparator{};
const auto separatorUpItem = AppBarSeparator{};
const auto separatorRightItem = AppBarSeparator{};
const auto separatorLeftItem = AppBarSeparator{};

splitPaneDownMenu.SecondaryCommands().Append(separatorDownItem);
splitPaneUpMenu.SecondaryCommands().Append(separatorUpItem);
splitPaneRightMenu.SecondaryCommands().Append(separatorRightItem);
splitPaneLeftMenu.SecondaryCommands().Append(separatorLeftItem);

for (auto profileIndex = 0; profileIndex < activeProfileCount; profileIndex++)
{
const auto profile = activeProfiles.GetAt(profileIndex);
const auto profileName = profile.Name();
const auto profileIcon = profile.Icon();

NewTerminalArgs args{};
args.Profile(profileName);

makeItem(profileName, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Down, .5, args } }, splitPaneDownMenu);
makeItem(profileName, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Up, .5, args } }, splitPaneUpMenu);
makeItem(profileName, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Right, .5, args } }, splitPaneRightMenu);
makeItem(profileName, profileIcon, ActionAndArgs{ ShortcutAction::SplitPane, SplitPaneArgs{ SplitType::Manual, SplitDirection::Left, .5, args } }, splitPaneLeftMenu);
}

MUX::Controls::CommandBarFlyout splitPaneMenu{};
makeMenuItem(RS_(L"SplitPaneDownText"), L"\xF246", splitPaneDownMenu, splitPaneMenu);
makeMenuItem(RS_(L"SplitPaneRightText"), L"\xF246", splitPaneRightMenu, splitPaneMenu);
makeMenuItem(RS_(L"SplitPaneUpText"), L"\xF246", splitPaneUpMenu, splitPaneMenu);
makeMenuItem(RS_(L"SplitPaneLeftText"), L"\xF246", splitPaneLeftMenu, splitPaneMenu);
makeMenuItem(RS_(L"SplitPaneText"), L"\xF246", splitPaneMenu, menu);

// Only wire up "Close Pane" if there's multiple panes.
if (_GetFocusedTabImpl()->GetLeafPaneCount() > 1)
{
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr });
MUX::Controls::CommandBarFlyout swapPaneMenu{};
const auto rootPane = _GetFocusedTabImpl()->GetRootPane();
const auto mruPanes = _GetFocusedTabImpl()->GetMruPanes();
auto activePane = _GetFocusedTabImpl()->GetActivePane();
rootPane->WalkTree([&](auto p) {
if (const auto& c{ p->GetTerminalControl() })
{
if (c == control)
{
activePane = p;
}
}
});

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Down, mruPanes))
dmitrykok marked this conversation as resolved.
Show resolved Hide resolved
{
makeItem(RS_(L"SwapPaneDownText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Down } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Right, mruPanes))
{
makeItem(RS_(L"SwapPaneRightText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Right } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Up, mruPanes))
{
makeItem(RS_(L"SwapPaneUpText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Up } }, swapPaneMenu);
}

if (auto neighbor = rootPane->NavigateDirection(activePane, FocusDirection::Left, mruPanes))
{
makeItem(RS_(L"SwapPaneLeftText"), neighbor->GetProfile().Icon(), ActionAndArgs{ ShortcutAction::SwapPane, SwapPaneArgs{ FocusDirection::Left } }, swapPaneMenu);
}

makeMenuItem(RS_(L"SwapPaneText"), L"\xF1CB", swapPaneMenu, menu);

makeItem(RS_(L"TogglePaneZoomText"), L"\xE8A3", ActionAndArgs{ ShortcutAction::TogglePaneZoom, nullptr }, menu);
makeItem(RS_(L"CloseOtherPanesText"), L"\xE89F", ActionAndArgs{ ShortcutAction::CloseOtherPanes, nullptr }, menu);
makeItem(RS_(L"PaneClose"), L"\xE89F", ActionAndArgs{ ShortcutAction::ClosePane, nullptr }, menu);
}

if (control.ConnectionState() >= ConnectionState::Closed)
{
makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr });
makeItem(RS_(L"RestartConnectionText"), L"\xE72C", ActionAndArgs{ ShortcutAction::RestartConnection, nullptr }, menu);
}

if (withSelection)
{
makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr });
makeItem(RS_(L"SearchWebText"), L"\xF6FA", ActionAndArgs{ ShortcutAction::SearchForText, nullptr }, menu);
}

makeItem(RS_(L"TabClose"), L"\xE711", ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex().value() } });
makeItem(RS_(L"TabClose"), L"\xE711", ActionAndArgs{ ShortcutAction::CloseTab, CloseTabArgs{ _GetFocusedTabIndex().value() } }, menu);
}

void TerminalPage::_PopulateQuickFixMenu(const TermControl& control,
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TerminalTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ namespace winrt::TerminalApp::implementation
winrt::TerminalApp::TaskbarState GetCombinedTaskbarState() const;

std::shared_ptr<Pane> GetRootPane() const { return _rootPane; }
std::vector<uint32_t> GetMruPanes() const { return _mruPanes; }

winrt::TerminalApp::TerminalTabStatus TabStatus()
{
Expand Down
16 changes: 8 additions & 8 deletions src/cascadia/TerminalControl/TermControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
x:Uid="SelectOutputButton"
Click="_SelectOutputHandler"
Icon="AlignLeft" />
<AppBarButton x:Name="SearchCommandButton"
x:Uid="SearchCommandButton"
Click="_SearchCommandHandler"
Icon="Find" />
</mux:CommandBarFlyout.SecondaryCommands>
</mux:CommandBarFlyout>

Expand All @@ -64,10 +68,6 @@
Click="_PasteCommandHandler"
Icon="Paste" />
<mux:CommandBarFlyout.SecondaryCommands>
<AppBarButton x:Name="SearchCommandButton"
x:Uid="SearchCommandButton"
Click="_SearchCommandHandler"
Icon="Find" />
<AppBarButton x:Name="SelectCommandWithSelectionButton"
x:Uid="SelectCommandWithSelectionButton"
Click="_SelectCommandHandler">
Expand All @@ -89,17 +89,17 @@
12dips. This is harder for folks to hit with the mouse, and isn't
consistent with the rest of the scrollbars on the platform (as much
as they can be).

To work around this, we have to entirely copy the template for the
ScrollBar into our XAML file. We're then also re-defining
ScrollBarSize here to 16, so that the new template will pick up on
the new value.

This is kinda a pain, and we have to be careful to be sure to ingest
an updated version of the template any time we update MUX. The
latest ControlsV2 version of the template can be found at:
https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/ScrollBar_themeresources.xaml#L218

Additionally we have:
* removed the corner radius, because that should be flush
with the top of the window above the TermControl.
Expand All @@ -108,7 +108,7 @@
the Win11-style WinUI ScrollView. If you also have the "Always show scrollbars" setting enabled in
the settings app (do it if you haven't already), it avoids any and all animations during startup which
makes the app start feel noticeably better and also shaves off another ~167ms of our "busy time".

We're also planning on making this adjustable in the future
(GH#9218), where we might need this anyways.
-->
Expand Down
Loading