Repository: microsoft/terminal (language: cpp)

Issue:
Add close pane to the tab context menu (when there are multiple panes)
<!-- 
🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨

I ACKNOWLEDGE THE FOLLOWING BEFORE PROCEEDING:
1. If I delete this entire template and go my own path, the core team may close my issue without further explanation or engagement.
2. If I list multiple bugs/concerns in this one issue, the core team may close my issue without further explanation or engagement.
3. If I write an issue that has many duplicates, the core team may close my issue without further explanation or engagement (and without necessarily spending time to find the exact duplicate ID number).
4. If I leave the title incomplete when filing the issue, the core team may close my issue without further explanation or engagement.
5. If I file something completely blank in the body, the core team may close my issue without further explanation or engagement.

All good? Then proceed!
-->

# Description of the new feature/enhancement

<!-- 
A clear and concise description of what the problem is that the new feature would solve.
Describe why and how a user would use this new functionality (if applicable).
-->

Once a tab is split, there's no way to return it to normal, meaning either having to continue working in half the space or starting a new tab and losing everything from the current one. It should allow for either closing one half or splitting them into two tabs.

# Proposed technical implementation details (optional)

<!-- 
A clear and concise description of what you want to happen.
-->



Discussion / hints:
You mean like the [`closePane` action](https://docs.microsoft.com/en-us/windows/terminal/panes#closing-a-pane)/?  Or maybe [moving panes to their own tabs](https://docs.microsoft.com/en-us/windows/terminal/panes#moving-panes)? Or heck even [zooming a pane](https://docs.microsoft.com/en-us/windows/terminal/panes#zooming-a-pane), to make it take the full size of the tab again?
I guess all three options would be nice, though I was mainly talking about the first. I didn't realize it was even an option since I didn't think to check the actions, and it's something I feel should be available via a menu and not just a shortcut, both to make it more obvious that it _is_ an option, and to make it easier to do without having to remember the shortcut, especially since it's likely not something most would use very often.

I see three ways of handling this. The cleanest, most space-efficient, and probably most obvious would be to add the actions to the tab's right-click menu, e.g. "Close active pane," "Move active pane to new tab," "Make active pane full-size" (zoom it), and "Close all non-active panes" (though this one could be dangerous and would probably benefit from a confirmation dialog). Then whichever pane is active when right-clicking the tab and selecting one of the options would be the one acted on.

The second possibility would be to add a small title bar to each pane that could be right-clicked, which would bring up a menu with the previous options, minus the word active or replacing it with "other" in the case of closing the other panes, of course.

The third option would be to add a few small buttons at the top-right of each pane, an x to close it, a square to maximize it or double square to restore it, and something like a square with an arrow for separating it out into a new tab.
FWIW, the general pattern the Terminal uses is that all the actions for the Terminal are in the Command Palette. We don't have a whole lot of UI space, so the command palette is a great way for us to have LOTS of actions while also making sure most menus aren't excessively cluttered. That being said

* Sure, okay, we can use this to track "Add close pane to the tab context menu (when there are multiple panes)"
* see: #4717
* This will probably also fit under the same feature set as above
how is this on the backlog?  How do people even use this half-baked capability?

@rismoney Probably because most people just close panes with the keyboard (<kbd>ctrl+shift+w</kbd>), or the Command Palette <kbd>ctrl+shift+p</kbd>. If you're passionate about the feature, I can try and help provide a roadmap of where the code changes would need to go. 
keyboard shortcuts ftw!
> @rismoney Probably because most people just close panes with the keyboard (ctrl+shift+w), or the Command Palette ctrl+shift+p. If you're passionate about the feature, I can try and help provide a roadmap of where the code changes would need to go.

@zadjii-msft I don't know if the offer is still on the table (or open to outside help), but I would love to take a crack at this and a roadmap would be extremely helpful!
Of course!

> **Note**
> ## Walkthrough

* I'd start by taking a look at `TerminalTab::_CreateContextMenu`, in `TerminalTab.cpp`. That's what we use for building all the other context menu entries for the tabs, so that's a good place to insert a new one. 
* I'd stash the `Controls::MenuFlyoutItem` that you make for `ClosePane` into the `TerminalTab` itself as a member. That way, we can use that member to toggle the visibility when the number of panes in the tab changes. 
* I'd start by setting the item to be `Visibility(Collapsed)`, so that it's not initially visible.
* `TerminalTab::SplitPane` is where new splits get added, so that would be a good place to change the `Visibility` to `Visible`
* in `TerminalTab::_AttachEventHandlersToPane`, we add a `pane->Closed` callback, which we could use to set the `Visibility` back to `Collapsed` if there's only one pane in the tree. 

<hr>

Lemme know if you need any more help!


![Image](https://user-images.githubusercontent.com/98557455/232645653-d1a09c90-5c90-4c59-ae40-52860ec73dee.gif)

I decided to take a crack at this one and I think I have the functionality working. What should we use for the icon in the context menu? 

Fix patch:
diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
index e3c992f1d9f..f8f45105018 100644
--- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
+++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw
@@ -763,15 +763,12 @@
   </data>
   <data name="AboutDialog_CheckingForUpdatesLabel.Text" xml:space="preserve">
     <value>Checking for updates...</value>
-    <comment></comment>
   </data>
   <data name="AboutDialog_UpdateAvailableLabel.Text" xml:space="preserve">
     <value>An update is available.</value>
-    <comment></comment>
   </data>
   <data name="AboutDialog_InstallUpdateButton.Content" xml:space="preserve">
     <value>Install now</value>
-    <comment></comment>
   </data>
   <data name="DuplicateRemainingProfilesEntry" xml:space="preserve">
     <value>The "newTabMenu" field contains more than one entry of type "remainingProfiles". Only the first one will be considered.</value>
@@ -820,4 +817,10 @@
   <data name="NewTabMenuFolderEmpty" xml:space="preserve">
     <value>Empty...</value>
   </data>
-</root>
+  <data name="ClosePaneText" xml:space="preserve">
+    <value>Close Pane</value>
+  </data>
+  <data name="ClosePaneToolTip" xml:space="preserve">
+    <value>Close the active pane if multiple panes are present</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/src/cascadia/TerminalApp/TerminalTab.cpp b/src/cascadia/TerminalApp/TerminalTab.cpp
index 446f74097f8..28a568a9de6 100644
--- a/src/cascadia/TerminalApp/TerminalTab.cpp
+++ b/src/cascadia/TerminalApp/TerminalTab.cpp
@@ -31,6 +31,8 @@ namespace winrt::TerminalApp::implementation
         _rootPane = rootPane;
         _activePane = nullptr;
 
+        _closePaneMenuItem.Visibility(WUX::Visibility::Collapsed);
+
         auto firstId = _nextPaneId;
 
         _rootPane->WalkTree([&](std::shared_ptr<Pane> pane) {
@@ -532,6 +534,9 @@ namespace winrt::TerminalApp::implementation
         // original pane first.
         auto [original, newPane] = _activePane->Split(splitType, splitSize, pane);
 
+        // After split, Close Pane Menu Item should be visible
+        _closePaneMenuItem.Visibility(WUX::Visibility::Visible);
+
         // The active pane has an id if it is a leaf
         if (activePaneId)
         {
@@ -1048,6 +1053,11 @@ namespace winrt::TerminalApp::implementation
             _mruPanes.insert(_mruPanes.begin(), paneId.value());
         }
 
+        if (_rootPane->GetLeafPaneCount() == 1)
+        {
+            _closePaneMenuItem.Visibility(WUX::Visibility::Collapsed);
+        }
+
         _RecalculateAndApplyReadOnly();
 
         // Raise our own ActivePaneChanged event.
@@ -1306,6 +1316,23 @@ namespace winrt::TerminalApp::implementation
             Automation::AutomationProperties::SetHelpText(splitTabMenuItem, splitTabToolTip);
         }
 
+        Controls::MenuFlyoutItem closePaneMenuItem = _closePaneMenuItem;
+        {
+            // "Close Pane"
+            closePaneMenuItem.Click([weakThis](auto&&, auto&&) {
+                if (auto tab{ weakThis.get() })
+                {
+                    tab->ClosePane();
+                }
+            });
+            closePaneMenuItem.Text(RS_(L"ClosePaneText"));
+
+            const auto closePaneToolTip = RS_(L"ClosePaneToolTip");
+
+            WUX::Controls::ToolTipService::SetToolTip(closePaneMenuItem, box_value(closePaneToolTip));
+            Automation::AutomationProperties::SetHelpText(closePaneMenuItem, closePaneToolTip);
+        }
+
         Controls::MenuFlyoutItem exportTabMenuItem;
         {
             // "Export Tab"
@@ -1357,6 +1384,7 @@ namespace winrt::TerminalApp::implementation
         contextMenuFlyout.Items().Append(renameTabMenuItem);
         contextMenuFlyout.Items().Append(duplicateTabMenuItem);
         contextMenuFlyout.Items().Append(splitTabMenuItem);
+        contextMenuFlyout.Items().Append(closePaneMenuItem);
         contextMenuFlyout.Items().Append(exportTabMenuItem);
         contextMenuFlyout.Items().Append(findMenuItem);
         contextMenuFlyout.Items().Append(menuSeparator);
diff --git a/src/cascadia/TerminalApp/TerminalTab.h b/src/cascadia/TerminalApp/TerminalTab.h
index 7809b9c7612..d45abd92001 100644
--- a/src/cascadia/TerminalApp/TerminalTab.h
+++ b/src/cascadia/TerminalApp/TerminalTab.h
@@ -113,6 +113,8 @@ namespace winrt::TerminalApp::implementation
         std::shared_ptr<Pane> _activePane{ nullptr };
         std::shared_ptr<Pane> _zoomedPane{ nullptr };
 
+        Windows::UI::Xaml::Controls::MenuFlyoutItem _closePaneMenuItem;
+
         winrt::hstring _lastIconPath{};
         std::optional<winrt::Windows::UI::Color> _runtimeTabColor{};
         winrt::TerminalApp::TabHeaderControl _headerControl{};


Test patch: