From 54292253c83335237f3f6a60bc93f23928aa2334 Mon Sep 17 00:00:00 2001 From: Pankaj Bhojwani Date: Wed, 29 Jan 2025 13:03:18 -0800 Subject: [PATCH] can change action, can edit args --- .../ActionsViewModel.cpp | 48 ++++++++----------- .../TerminalSettingsEditor/ActionsViewModel.h | 1 + .../TerminalSettingsEditor/EditAction.cpp | 22 +++++++++ .../TerminalSettingsEditor/EditAction.h | 6 +++ .../TerminalSettingsEditor/EditAction.xaml | 38 +++++++++------ .../TerminalSettingsModel/ActionArgsMagic.h | 6 +-- .../CascadiaSettings.cpp | 12 +++++ .../TerminalSettingsModel/CascadiaSettings.h | 1 + .../CascadiaSettings.idl | 2 + 9 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp index be2307507f..867f7ac956 100644 --- a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp @@ -126,9 +126,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation CurrentAction(cmd.Name()); std::vector shortcutActions; - for (const auto [_, name] : _AvailableActionsAndNamesMap) + for (const auto [action, name] : _AvailableActionsAndNamesMap) { shortcutActions.emplace_back(name); + _NameToActionMap.emplace(name, action); } _AvailableShortcutActions = single_threaded_observable_vector(std::move(shortcutActions)); @@ -147,21 +148,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation if (viewModelProperty == L"ProposedShortcutAction") { // todo: maybe just put this logic in the ProposedShortcutAction setter? - // todo: need a translator between string and enum // todo: need a 'default arg struct' generator? - Model::ActionAndArgs newActionAndArgs{}; const auto actionString = unbox_value(ProposedShortcutAction()); - if (actionString == L"Send Input") - { - newActionAndArgs.Action(Model::ShortcutAction::SendInput); - newActionAndArgs.Args(Model::SendInputArgs{ L"" }); - } - else if (actionString == L"Close Tab") - { - const uint32_t index{ 0 }; - newActionAndArgs.Action(Model::ShortcutAction::CloseTab); - newActionAndArgs.Args(Model::CloseTabArgs{ index }); - } + const auto actionEnum = _NameToActionMap.at(actionString); + Model::ActionAndArgs newActionAndArgs{ actionEnum, CascadiaSettings::GetEmptyArgsForAction(actionEnum) }; _command.ActionAndArgs(newActionAndArgs); ActionArgsVM(make(newActionAndArgs)); } @@ -253,20 +243,24 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation std::vector argValues; for (uint32_t i = 0; i < shortcutArgsNumItems; i++) { - const auto argType = shortcutArgs.GetArgDescriptionAt(i).Type; - const auto item = make(argType, shortcutArgs.GetArgAt(i)); - item.PropertyChanged([&](const IInspectable& sender, const PropertyChangedEventArgs& args) { - const auto itemProperty{ args.PropertyName() }; - if (itemProperty == L"Value") - { - const auto argWrapper = sender.as(); - const auto newValue = argWrapper.Value(); - // todo: this works but for some reason we have to hit "Save" twice (just for the first time...)? - _actionAndArgs.Args().SetArgAt(i, newValue); - } - }); - argValues.push_back(item); + const auto argAtIndex = shortcutArgs.GetArgAt(i); + if (argAtIndex) + { + const auto argType = shortcutArgs.GetArgDescriptionAt(i).Type; + const auto item = make(argType, argAtIndex); + item.PropertyChanged([&, i](const IInspectable& sender, const PropertyChangedEventArgs& args) { + const auto itemProperty{ args.PropertyName() }; + if (itemProperty == L"Value") + { + const auto argWrapper = sender.as(); + const auto newValue = argWrapper.Value(); + _actionAndArgs.Args().SetArgAt(i, newValue); + } + }); + argValues.push_back(item); + } } + _ArgValues = single_threaded_observable_vector(std::move(argValues)); } } diff --git a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h index 5f48e13b9d..db1c5af1dc 100644 --- a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h @@ -162,6 +162,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void _RegisterKeyChordVMEvents(Editor::KeyChordViewModel kcVM); void _RegisterActionArgsVMEvents(Editor::ActionArgsViewModel actionArgsVM); Windows::Foundation::Collections::IMap _AvailableActionsAndNamesMap; + std::unordered_map _NameToActionMap; }; struct ArgWrapper : ArgWrapperT, ViewModelHelper diff --git a/src/cascadia/TerminalSettingsEditor/EditAction.cpp b/src/cascadia/TerminalSettingsEditor/EditAction.cpp index 8d6d6e2522..a085d05b6b 100644 --- a/src/cascadia/TerminalSettingsEditor/EditAction.cpp +++ b/src/cascadia/TerminalSettingsEditor/EditAction.cpp @@ -15,10 +15,32 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation EditAction::EditAction() { InitializeComponent(); + _itemTemplateSelector = Resources().Lookup(winrt::box_value(L"ArgsTemplateSelector")).try_as(); + _listItemTemplate = Resources().Lookup(winrt::box_value(L"ListItemTemplate")).try_as(); } void EditAction::OnNavigatedTo(const NavigationEventArgs& e) { _ViewModel = e.Parameter().as(); } + + void EditAction::_choosingItemContainer( + const Windows::UI::Xaml::Controls::ListViewBase& /*sender*/, + const Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs& args) + { + const auto dataTemplate = _itemTemplateSelector.SelectTemplate(args.Item()); + const auto itemContainer = args.ItemContainer(); + + // todo: do we need the same caching logic as in command palette? + if (!itemContainer || itemContainer.ContentTemplate() != dataTemplate) + { + ElementFactoryGetArgs factoryArgs{}; + const auto listViewItem = _listItemTemplate.GetElement(factoryArgs).try_as(); + listViewItem.ContentTemplate(dataTemplate); + + args.ItemContainer(listViewItem); + } + + args.IsContainerPrepared(true); + } } diff --git a/src/cascadia/TerminalSettingsEditor/EditAction.h b/src/cascadia/TerminalSettingsEditor/EditAction.h index 46bf257cf3..9bab08c52d 100644 --- a/src/cascadia/TerminalSettingsEditor/EditAction.h +++ b/src/cascadia/TerminalSettingsEditor/EditAction.h @@ -19,6 +19,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation til::property_changed_event PropertyChanged; WINRT_OBSERVABLE_PROPERTY(Editor::CommandViewModel, ViewModel, PropertyChanged.raise, nullptr); + + private: + friend struct EditActionT; // for Xaml to bind events + Windows::UI::Xaml::DataTemplate _listItemTemplate; + winrt::Microsoft::Terminal::Settings::Editor::ArgsTemplateSelectors _itemTemplateSelector{ nullptr }; + void _choosingItemContainer(const Windows::UI::Xaml::Controls::ListViewBase& sender, const Windows::UI::Xaml::Controls::ChoosingItemContainerEventArgs& args); }; } diff --git a/src/cascadia/TerminalSettingsEditor/EditAction.xaml b/src/cascadia/TerminalSettingsEditor/EditAction.xaml index 302770d2fa..f0d1bf70af 100644 --- a/src/cascadia/TerminalSettingsEditor/EditAction.xaml +++ b/src/cascadia/TerminalSettingsEditor/EditAction.xaml @@ -235,24 +235,31 @@ - + + + - - - + + + + + - - - + + + + + - + diff --git a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h index e3edf03eb8..c6d52238c5 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h @@ -76,7 +76,7 @@ struct InitListPlaceholder #define EQUALS_ARGS(type, name, jsonKey, required, ...) \ &&(otherAsUs->_##name == _##name) -// getter and setter for each property by name +// getter and setter for each property by index #define GET_ARG_BY_INDEX(type, name, jsonKey, required, ...) \ if (index == curIndex++) \ { \ @@ -86,7 +86,7 @@ struct InitListPlaceholder } \ else \ { \ - return nullptr; \ + return winrt::box_value(type{ __VA_ARGS__ }); \ } \ } @@ -138,7 +138,7 @@ struct InitListPlaceholder // * GlobalSummonArgs has the QuakeModeFromJson helper #define ACTION_ARG_BODY(className, argsMacro) \ - className() = default; \ + className() { argsMacro(APPEND_ARG_DESCRIPTION) }; \ className( \ argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \ argsMacro(CTOR_INIT) _placeholder{} { \ diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index ebf480e39e..3c667e7e8f 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -994,6 +994,18 @@ winrt::Windows::Foundation::Collections::IMap(); + case Model::ShortcutAction::MovePane: + return winrt::make(); + default: + return nullptr; + } +} // Method Description: // - Determines if we're on an OS platform that supports diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h index a9b44a6f53..d1e6166e06 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.h +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.h @@ -116,6 +116,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation static bool IsPortableMode(); static Windows::Foundation::Collections::IMap AvailableShortcutActionsAndNames(); + static Model::IActionArgs GetEmptyArgsForAction(Model::ShortcutAction shortcutAction); CascadiaSettings() noexcept = default; CascadiaSettings(const winrt::hstring& userJSON, const winrt::hstring& inboxJSON); diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl index a3af68b965..532947f1bf 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.idl @@ -5,6 +5,7 @@ import "GlobalAppSettings.idl"; import "Profile.idl"; import "TerminalWarnings.idl"; import "DefaultTerminal.idl"; +import "ActionArgs.idl"; namespace Microsoft.Terminal.Settings.Model { @@ -21,6 +22,7 @@ namespace Microsoft.Terminal.Settings.Model static String ApplicationVersion { get; }; static Windows.Foundation.Collections.IMap AvailableShortcutActionsAndNames { get; }; + static IActionArgs GetEmptyArgsForAction(Microsoft.Terminal.Settings.Model.ShortcutAction shortcutAction); CascadiaSettings(String userJSON, String inboxJSON);