Skip to content

Commit d14a984

Browse files
committed
PRE-MERGE microsoft#17281 Allow actions in the new tab dropdown
2 parents cf50777 + 0dff336 commit d14a984

13 files changed

+179
-4
lines changed

doc/cascadia/profiles.schema.json

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,8 @@
629629
"folder",
630630
"separator",
631631
"remainingProfiles",
632-
"matchProfiles"
632+
"matchProfiles",
633+
"action"
633634
]
634635
},
635636
"NewTabMenuEntry": {
@@ -781,6 +782,28 @@
781782
}
782783
]
783784
},
785+
"ActionEntry": {
786+
"description": "An action in the new tab dropdown",
787+
"allOf": [
788+
{
789+
"$ref": "#/$defs/NewTabMenuEntry"
790+
},
791+
{
792+
"type": "object",
793+
"properties": {
794+
"type": {
795+
"type": "string",
796+
"const": "action"
797+
},
798+
"profile": {
799+
"type": "string",
800+
"default": "",
801+
"description": "The ID of the action to show in this entry"
802+
}
803+
}
804+
}
805+
]
806+
},
784807
"SwitchToAdjacentTabArgs": {
785808
"oneOf": [
786809
{
@@ -2054,6 +2077,9 @@
20542077
},
20552078
{
20562079
"$ref": "#/$defs/RemainingProfilesEntry"
2080+
},
2081+
{
2082+
"$ref": "#/$defs/ActionEntry"
20572083
}
20582084
]
20592085
}

src/cascadia/TerminalApp/TerminalPage.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,18 @@ namespace winrt::TerminalApp::implementation
10041004
items.push_back(profileItem);
10051005
break;
10061006
}
1007+
case NewTabMenuEntryType::Action:
1008+
{
1009+
const auto actionEntry = entry.as<ActionEntry>();
1010+
const auto actionId = actionEntry.ActionId();
1011+
if (_settings.ActionMap().GetActionById(actionId))
1012+
{
1013+
auto actionItem = _CreateNewTabFlyoutAction(actionId);
1014+
items.push_back(actionItem);
1015+
}
1016+
1017+
break;
1018+
}
10071019
}
10081020
}
10091021

@@ -1094,6 +1106,42 @@ namespace winrt::TerminalApp::implementation
10941106
return profileMenuItem;
10951107
}
10961108

1109+
// Method Description:
1110+
// - This method creates a flyout menu item for a given action
1111+
// It makes sure to set the correct icon, keybinding, and click-action.
1112+
WUX::Controls::MenuFlyoutItem TerminalPage::_CreateNewTabFlyoutAction(const winrt::hstring& actionId)
1113+
{
1114+
auto actionMenuItem = WUX::Controls::MenuFlyoutItem{};
1115+
const auto action{ _settings.ActionMap().GetActionById(actionId) };
1116+
const auto actionKeyChord{ _settings.ActionMap().GetKeyBindingForAction(actionId) };
1117+
1118+
if (actionKeyChord)
1119+
{
1120+
_SetAcceleratorForMenuItem(actionMenuItem, actionKeyChord);
1121+
}
1122+
1123+
const auto actionName = action.Name();
1124+
actionMenuItem.Text(actionName);
1125+
1126+
// If there's an icon set for this action, set it as the icon for
1127+
// this flyout item
1128+
const auto& iconPath = action.IconPath();
1129+
if (!iconPath.empty())
1130+
{
1131+
const auto icon = _CreateNewTabFlyoutIcon(iconPath);
1132+
actionMenuItem.Icon(icon);
1133+
}
1134+
1135+
actionMenuItem.Click([action, weakThis{ get_weak() }](auto&&, auto&&) {
1136+
if (auto page{ weakThis.get() })
1137+
{
1138+
page->_actionDispatch->DoAction(action.ActionAndArgs());
1139+
}
1140+
});
1141+
1142+
return actionMenuItem;
1143+
}
1144+
10971145
// Method Description:
10981146
// - Helper method to create an IconElement that can be passed to MenuFlyoutItems and
10991147
// MenuFlyoutSubItems

src/cascadia/TerminalApp/TerminalPage.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ namespace winrt::TerminalApp::implementation
300300
std::vector<winrt::Windows::UI::Xaml::Controls::MenuFlyoutItemBase> _CreateNewTabFlyoutItems(winrt::Windows::Foundation::Collections::IVector<Microsoft::Terminal::Settings::Model::NewTabMenuEntry> entries);
301301
winrt::Windows::UI::Xaml::Controls::IconElement _CreateNewTabFlyoutIcon(const winrt::hstring& icon);
302302
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _CreateNewTabFlyoutProfile(const Microsoft::Terminal::Settings::Model::Profile profile, int profileIndex);
303+
winrt::Windows::UI::Xaml::Controls::MenuFlyoutItem _CreateNewTabFlyoutAction(const winrt::hstring& actionId);
303304

304305
void _OpenNewTabDropdown();
305306
HRESULT _OpenNewTab(const Microsoft::Terminal::Settings::Model::INewContentArgs& newContentArgs);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT license.
3+
4+
#include "pch.h"
5+
#include "ActionEntry.h"
6+
#include "JsonUtils.h"
7+
8+
#include "ActionEntry.g.cpp"
9+
10+
using namespace Microsoft::Terminal::Settings::Model;
11+
using namespace winrt::Microsoft::Terminal::Settings::Model::implementation;
12+
13+
static constexpr std::string_view ActionIdKey{ "actionId" };
14+
15+
ActionEntry::ActionEntry() noexcept :
16+
ActionEntryT<ActionEntry, NewTabMenuEntry>(NewTabMenuEntryType::Action)
17+
{
18+
}
19+
20+
Json::Value ActionEntry::ToJson() const
21+
{
22+
auto json = NewTabMenuEntry::ToJson();
23+
24+
JsonUtils::SetValueForKey(json, ActionIdKey, _ActionId);
25+
26+
return json;
27+
}
28+
29+
winrt::com_ptr<NewTabMenuEntry> ActionEntry::FromJson(const Json::Value& json)
30+
{
31+
auto entry = winrt::make_self<ActionEntry>();
32+
33+
JsonUtils::GetValueForKey(json, ActionIdKey, entry->_ActionId);
34+
35+
return entry;
36+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*++
2+
Copyright (c) Microsoft Corporation
3+
Licensed under the MIT license.
4+
5+
Module Name:
6+
- ActionEntry.h
7+
8+
Abstract:
9+
- An action entry in the "new tab" dropdown menu
10+
11+
Author(s):
12+
- Pankaj Bhojwani - May 2024
13+
14+
--*/
15+
#pragma once
16+
17+
#include "NewTabMenuEntry.h"
18+
#include "ActionEntry.g.h"
19+
20+
namespace winrt::Microsoft::Terminal::Settings::Model::implementation
21+
{
22+
struct ActionEntry : ActionEntryT<ActionEntry, NewTabMenuEntry>
23+
{
24+
public:
25+
ActionEntry() noexcept;
26+
27+
Json::Value ToJson() const override;
28+
static com_ptr<NewTabMenuEntry> FromJson(const Json::Value& json);
29+
30+
WINRT_PROPERTY(winrt::hstring, ActionId);
31+
};
32+
}
33+
34+
namespace winrt::Microsoft::Terminal::Settings::Model::factory_implementation
35+
{
36+
BASIC_FACTORY(ActionEntry);
37+
}

src/cascadia/TerminalSettingsModel/ActionMap.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
591591
return _GetActionByKeyChordInternal(keys).value_or(nullptr);
592592
}
593593

594+
Model::Command ActionMap::GetActionById(const winrt::hstring& cmdID) const
595+
{
596+
return _GetActionByID(cmdID);
597+
}
598+
594599
// Method Description:
595600
// - Retrieves the assigned command ID with the given key chord.
596601
// - Can return nullopt to differentiate explicit unbinding vs lack of binding.

src/cascadia/TerminalSettingsModel/ActionMap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
6060

6161
// queries
6262
Model::Command GetActionByKeyChord(const Control::KeyChord& keys) const;
63+
Model::Command GetActionById(const winrt::hstring& cmdID) const;
6364
bool IsKeyChordExplicitlyUnbound(const Control::KeyChord& keys) const;
6465
Control::KeyChord GetKeyBindingForAction(const winrt::hstring& cmdID);
6566

src/cascadia/TerminalSettingsModel/ActionMap.idl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Microsoft.Terminal.Settings.Model
1111
Boolean IsKeyChordExplicitlyUnbound(Microsoft.Terminal.Control.KeyChord keys);
1212

1313
Command GetActionByKeyChord(Microsoft.Terminal.Control.KeyChord keys);
14-
14+
Command GetActionById(String cmdID);
1515
Microsoft.Terminal.Control.KeyChord GetKeyBindingForAction(String cmdID);
1616

1717
Windows.Foundation.Collections.IMapView<String, ActionAndArgs> AvailableActions { get; };

src/cascadia/TerminalSettingsModel/Microsoft.Terminal.Settings.ModelLib.vcxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
<ClInclude Include="SeparatorEntry.h">
2929
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
3030
</ClInclude>
31+
<ClInclude Include="ActionEntry.h">
32+
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
33+
</ClInclude>
3134
<ClInclude Include="FolderEntry.h">
3235
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
3336
</ClInclude>
@@ -185,6 +188,9 @@
185188
<ClCompile Include="SeparatorEntry.cpp">
186189
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
187190
</ClCompile>
191+
<ClCompile Include="ActionEntry.cpp">
192+
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
193+
</ClCompile>
188194
<ClCompile Include="FolderEntry.cpp">
189195
<DependentUpon>NewTabMenuEntry.idl</DependentUpon>
190196
</ClCompile>

src/cascadia/TerminalSettingsModel/NewTabMenuEntry.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "SeparatorEntry.h"
99
#include "FolderEntry.h"
1010
#include "ProfileEntry.h"
11+
#include "ActionEntry.h"
1112
#include "RemainingProfilesEntry.h"
1213
#include "MatchProfilesEntry.h"
1314

@@ -52,6 +53,8 @@ winrt::com_ptr<NewTabMenuEntry> NewTabMenuEntry::FromJson(const Json::Value& jso
5253
return RemainingProfilesEntry::FromJson(json);
5354
case NewTabMenuEntryType::MatchProfiles:
5455
return MatchProfilesEntry::FromJson(json);
56+
case NewTabMenuEntryType::Action:
57+
return ActionEntry::FromJson(json);
5558
default:
5659
return nullptr;
5760
}

0 commit comments

Comments
 (0)