From c8e2e087636db9c4d33771628c04d8fcb9cb0b27 Mon Sep 17 00:00:00 2001 From: Pankaj Bhojwani Date: Mon, 28 Apr 2025 16:48:23 -0700 Subject: [PATCH] new tab, new window, split pane --- .../ActionsViewModel.cpp | 70 ++++++- .../TerminalSettingsEditor/ActionsViewModel.h | 6 + .../ActionsViewModel.idl | 6 + .../ArgsTemplateSelectors.cpp | 19 +- .../ArgsTemplateSelectors.h | 3 + .../ArgsTemplateSelectors.idl | 3 + .../TerminalSettingsEditor/EditAction.xaml | 64 ++++++ .../Resources/en-US/Resources.resw | 36 ++++ .../TerminalSettingsModel/ActionArgs.h | 196 ++++++++++-------- .../TerminalSettingsModel/ActionArgs.idl | 6 +- .../TerminalSettingsModel/ActionArgsMagic.h | 63 ++++-- .../CascadiaSettings.cpp | 6 + .../TerminalSettingsModel/EnumMappings.cpp | 2 + .../TerminalSettingsModel/EnumMappings.h | 2 + .../TerminalSettingsModel/EnumMappings.idl | 2 + 15 files changed, 365 insertions(+), 119 deletions(-) diff --git a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp index 92667d9c22..9b2da5e737 100644 --- a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.cpp @@ -25,17 +25,13 @@ using namespace winrt::Windows::UI::Xaml::Navigation; using namespace winrt::Microsoft::Terminal::Settings::Model; // todo: -// INewContentArgs // multiple actions // selection color // the above arg types aren't implemented yet - they all have multiple values within them -// and require a different approach to binding/displaying. INewContentArgs is a bunch of args -// in one object, selected color has color and IsIndex16, multiple actions is... multiple actions +// and require a different approach to binding/displaying. Selection color has color and IsIndex16, +// multiple actions is... multiple actions // for now, do not support these shortcut actions in the new action editor inline const std::set UnimplementedShortcutActions = { - winrt::Microsoft::Terminal::Settings::Model::ShortcutAction::NewTab, - winrt::Microsoft::Terminal::Settings::Model::ShortcutAction::SplitPane, - winrt::Microsoft::Terminal::Settings::Model::ShortcutAction::NewWindow, winrt::Microsoft::Terminal::Settings::Model::ShortcutAction::MultipleActions, winrt::Microsoft::Terminal::Settings::Model::ShortcutAction::ColorSelection }; @@ -325,12 +321,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation const auto actionString = unbox_value(ProposedShortcutAction()); const auto actionEnum = _NameToActionMap.at(actionString); const auto emptyArgs = CascadiaSettings::GetEmptyArgsForAction(actionEnum); - // todo: for sendInput, where "input" is a required argument, this will set it to an empty string which does not satisfy the requirement + // todo: probably need some better default values for empty args + // eg. for sendInput, where "input" is a required argument, "input" gets set to an empty string which does not satisfy the requirement // i.e. if the user hits "save" immediately after switching to sendInput as the action (without adding something to the input field), they'll get an error - if (emptyArgs) - { - emptyArgs.SetAllArgsToDefault(); - } + // there are some other cases as well Model::ActionAndArgs newActionAndArgs{ actionEnum, emptyArgs }; _command.ActionAndArgs(newActionAndArgs); const auto actionArgsVM = make_self(newActionAndArgs); @@ -483,6 +477,14 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { INITIALIZE_ENUM_LIST_AND_VALUE(SelectOutputDirection, Model::SelectOutputDirection, L"Actions_SelectOutputDirection", L"Content"); } + else if (_type == L"Model::SplitDirection") + { + INITIALIZE_ENUM_LIST_AND_VALUE(SplitDirection, Model::SplitDirection, L"Actions_SplitDirection", L"Content"); + } + else if (_type == L"SplitType") + { + INITIALIZE_ENUM_LIST_AND_VALUE(SplitType, Model::SplitType, L"Actions_SplitType", L"Content"); + } else if (_type == L"Windows::Foundation::IReference") { INITIALIZE_NULLABLE_ENUM_LIST_AND_VALUE(TabSwitcherMode, Model::TabSwitcherMode, L"Actions_TabSwitcherMode", L"Content"); @@ -512,11 +514,29 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return winrt::unbox_value(value); } + winrt::hstring ArgWrapper::UnboxGuid(const Windows::Foundation::IInspectable& value) + { + return winrt::to_hstring(winrt::unbox_value(value)); + } + int32_t ArgWrapper::UnboxInt32(const Windows::Foundation::IInspectable& value) { return winrt::unbox_value(value); } + float ArgWrapper::UnboxInt32Optional(const Windows::Foundation::IInspectable& value) + { + const auto unboxed = winrt::unbox_value>(value); + if (unboxed) + { + return static_cast(unboxed.Value()); + } + else + { + return NAN; + } + } + uint32_t ArgWrapper::UnboxUInt32(const Windows::Foundation::IInspectable& value) { return winrt::unbox_value(value); @@ -535,6 +555,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + float ArgWrapper::UnboxUInt64(const Windows::Foundation::IInspectable& value) + { + return static_cast(winrt::unbox_value(value)); + } + float ArgWrapper::UnboxFloat(const Windows::Foundation::IInspectable& value) { return winrt::unbox_value(value); @@ -580,11 +605,29 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation Value(box_value(newValue)); } + void ArgWrapper::GuidBindBack(const winrt::hstring& newValue) + { + // todo: probably need some validation? + Value(box_value(winrt::guid{ newValue })); + } + void ArgWrapper::Int32BindBack(const double newValue) { Value(box_value(static_cast(newValue))); } + void ArgWrapper::Int32OptionalBindBack(const double newValue) + { + if (!isnan(newValue)) + { + Value(box_value(static_cast(newValue))); + } + else + { + Value(nullptr); + } + } + void ArgWrapper::UInt32BindBack(const double newValue) { Value(box_value(static_cast(newValue))); @@ -602,6 +645,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation } } + void ArgWrapper::UInt64BindBack(const double newValue) + { + Value(box_value(static_cast(newValue))); + } + void ArgWrapper::FloatBindBack(const double newValue) { Value(box_value(static_cast(newValue))); diff --git a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h index 9ec3a16d93..95ecee26bc 100644 --- a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.h @@ -183,9 +183,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // unboxing functions winrt::hstring UnboxString(const Windows::Foundation::IInspectable& value); + winrt::hstring UnboxGuid(const Windows::Foundation::IInspectable& value); int32_t UnboxInt32(const Windows::Foundation::IInspectable& value); + float UnboxInt32Optional(const Windows::Foundation::IInspectable& value); uint32_t UnboxUInt32(const Windows::Foundation::IInspectable& value); float UnboxUInt32Optional(const Windows::Foundation::IInspectable& value); + float UnboxUInt64(const Windows::Foundation::IInspectable& value); float UnboxFloat(const Windows::Foundation::IInspectable& value); winrt::Windows::Foundation::IReference UnboxBoolOptional(const Windows::Foundation::IInspectable& value); winrt::Windows::Foundation::IReference UnboxTerminalCoreColorOptional(const Windows::Foundation::IInspectable& value); @@ -193,9 +196,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // bind back functions void StringBindBack(const winrt::hstring& newValue); + void GuidBindBack(const winrt::hstring& newValue); void Int32BindBack(const double newValue); + void Int32OptionalBindBack(const double newValue); void UInt32BindBack(const double newValue); void UInt32OptionalBindBack(const double newValue); + void UInt64BindBack(const double newValue); void FloatBindBack(const double newValue); void BoolBindBack(const Windows::Foundation::IReference newValue); void TerminalCoreColorBindBack(const winrt::Windows::Foundation::IReference newValue); diff --git a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.idl b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.idl index 48d652a172..af624632bf 100644 --- a/src/cascadia/TerminalSettingsEditor/ActionsViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/ActionsViewModel.idl @@ -91,9 +91,12 @@ namespace Microsoft.Terminal.Settings.Editor // unboxing functions String UnboxString(Object value); + String UnboxGuid(Object value); UInt32 UnboxInt32(Object value); + Single UnboxInt32Optional(Object value); UInt32 UnboxUInt32(Object value); Single UnboxUInt32Optional(Object value); + Single UnboxUInt64(Object value); Single UnboxFloat(Object value); Windows.Foundation.IReference UnboxBoolOptional(Object value); Windows.Foundation.IReference UnboxTerminalCoreColorOptional(Object value); @@ -101,9 +104,12 @@ namespace Microsoft.Terminal.Settings.Editor // bind back functions void StringBindBack(String newValue); + void GuidBindBack(String newValue); void Int32BindBack(Double newValue); + void Int32OptionalBindBack(Double newValue); void UInt32BindBack(Double newValue); void UInt32OptionalBindBack(Double newValue); + void UInt64BindBack(Double newValue); void FloatBindBack(Double newValue); void BoolBindBack(Windows.Foundation.IReference newValue); void TerminalCoreColorBindBack(Windows.Foundation.IReference newValue); diff --git a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp index 001408f647..bf8d8d41ed 100644 --- a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp +++ b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.cpp @@ -30,6 +30,10 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { return StringTemplate(); } + else if (argType == L"winrt::guid") + { + return GuidTemplate(); + } else if (argType == L"int32_t") { return Int32Template(); @@ -38,15 +42,24 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation { return UInt32Template(); } + else if (argType == L"uint64_t") + { + return UInt64Template(); + } else if (argType == L"float") { return FloatTemplate(); } - else if (argType == L"bool") + else if (argType == L"bool" || + argType == L"Windows::Foundation::IReference") { // we don't have any bool args that are required, so just use the optional template for all of them return BoolOptionalTemplate(); } + else if (argType == L"Windows::Foundation::IReference") + { + return Int32OptionalTemplate(); + } else if (argType == L"Windows::Foundation::IReference") { return UInt32OptionalTemplate(); @@ -62,7 +75,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation argType == L"Model::MonitorBehavior" || argType == L"winrt::Microsoft::Terminal::Control::ClearBufferType" || argType == L"SelectOutputDirection" || - argType == L"Windows::Foundation::IReference") + argType == L"Windows::Foundation::IReference" || + argType == L"Model::SplitDirection" || + argType == L"SplitType") { return EnumTemplate(); } diff --git a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h index 6d415fd40c..ddf2a72794 100644 --- a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h +++ b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.h @@ -15,9 +15,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation Windows::UI::Xaml::DataTemplate SelectTemplateCore(const winrt::Windows::Foundation::IInspectable&); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, NoArgTemplate); + WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, GuidTemplate); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, Int32Template); + WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, Int32OptionalTemplate); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt32Template); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt32OptionalTemplate); + WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, UInt64Template); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, FloatTemplate); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, StringTemplate); WINRT_PROPERTY(winrt::Windows::UI::Xaml::DataTemplate, BoolOptionalTemplate); diff --git a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.idl b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.idl index f1818a7eff..886df41833 100644 --- a/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.idl +++ b/src/cascadia/TerminalSettingsEditor/ArgsTemplateSelectors.idl @@ -8,9 +8,12 @@ namespace Microsoft.Terminal.Settings.Editor ArgsTemplateSelectors(); Windows.UI.Xaml.DataTemplate NoArgTemplate; + Windows.UI.Xaml.DataTemplate GuidTemplate; Windows.UI.Xaml.DataTemplate Int32Template; + Windows.UI.Xaml.DataTemplate Int32OptionalTemplate; Windows.UI.Xaml.DataTemplate UInt32Template; Windows.UI.Xaml.DataTemplate UInt32OptionalTemplate; + Windows.UI.Xaml.DataTemplate UInt64Template; Windows.UI.Xaml.DataTemplate FloatTemplate; Windows.UI.Xaml.DataTemplate StringTemplate; Windows.UI.Xaml.DataTemplate BoolOptionalTemplate; diff --git a/src/cascadia/TerminalSettingsEditor/EditAction.xaml b/src/cascadia/TerminalSettingsEditor/EditAction.xaml index b810711eac..0deb44bede 100644 --- a/src/cascadia/TerminalSettingsEditor/EditAction.xaml +++ b/src/cascadia/TerminalSettingsEditor/EditAction.xaml @@ -298,6 +298,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -337,6 +381,23 @@ + + + + + + + + + + + + + @@ -459,10 +520,13 @@ RTF An option to choose from for the "copy format". Copies content in Rich Text Format (RTF). + + Automatic + An option to choose from for the "split direction". Automatically determines the split direction. + + + Up + An option to choose from for the "split direction". Splits upward. + + + Right + An option to choose from for the "split direction". Splits to the right. + + + Down + An option to choose from for the "split direction". Splits downward. + + + Left + An option to choose from for the "split direction". Splits to the left. + + + Vertical + An option to choose from for the "split direction". Splits to the left. + + + Horizontal + An option to choose from for the "split direction". Splits to the left. + + + Manual + An option to choose from for the "split type". Creates a manual split. + + + Duplicate + An option to choose from for the "split type". Creates a split by duplicating the current session. + None An option to choose from for the "resize direction". None option. diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.h b/src/cascadia/TerminalSettingsModel/ActionArgs.h index f37f116166..f513ccd253 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.h @@ -286,6 +286,28 @@ protected: \ X(winrt::Microsoft::Terminal::Control::SelectionColor, Background, "background", false, nullptr) \ X(winrt::Microsoft::Terminal::Core::MatchMode, MatchMode, "matchMode", false, winrt::Microsoft::Terminal::Core::MatchMode::None) +//////////////////////////////////////////////////////////////////////////////// +#define NEW_TERMINAL_ARGS(X) \ + X(winrt::hstring, Commandline, "commandline", false, L"") \ + X(winrt::hstring, StartingDirectory, "startingDirectory", false, L"") \ + X(winrt::hstring, TabTitle, "tabTitle", false, L"") \ + X(Windows::Foundation::IReference, TabColor, "tabColor", false, nullptr) \ + X(Windows::Foundation::IReference, ProfileIndex, "index", false, nullptr) \ + X(winrt::hstring, Profile, "profile", false, L"") \ + X(winrt::guid, SessionId, "sessionId", false, winrt::guid{}) \ + X(bool, AppendCommandLine, "appendCommandLine", false, false) \ + X(Windows::Foundation::IReference, SuppressApplicationTitle, "suppressApplicationTitle", false, nullptr) \ + X(winrt::hstring, ColorScheme, "colorScheme", args->SchemeName().empty(), L"") \ + X(Windows::Foundation::IReference, Elevate, "elevate", false, nullptr) \ + X(Windows::Foundation::IReference, ReloadEnvironmentVariables, "reloadEnvironmentVariables", false, nullptr) \ + X(uint64_t, ContentId, "__content", false, 0) + +//////////////////////////////////////////////////////////////////////////////// +#define SPLIT_PANE_ARGS(X) \ + X(Model::SplitDirection, SplitDirection, "split", false, SplitDirection::Automatic) \ + X(SplitType, SplitMode, "splitMode", false, SplitType::Manual) \ + X(float, SplitSize, "size", false, 0.5f) + //////////////////////////////////////////////////////////////////////////////// namespace winrt::Microsoft::Terminal::Settings::Model::implementation @@ -358,41 +380,14 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // assumptions made in the macro. struct NewTerminalArgs : public NewTerminalArgsT { - NewTerminalArgs() = default; - NewTerminalArgs(int32_t& profileIndex) : - _ProfileIndex{ profileIndex } {}; - + PARTIAL_ACTION_ARG_BODY(NewTerminalArgs, NEW_TERMINAL_ARGS); ACTION_ARG(winrt::hstring, Type, L""); - ACTION_ARG(winrt::hstring, Commandline, L""); - ACTION_ARG(winrt::hstring, StartingDirectory, L""); - ACTION_ARG(winrt::hstring, TabTitle, L""); - ACTION_ARG(Windows::Foundation::IReference, TabColor, nullptr); - ACTION_ARG(Windows::Foundation::IReference, ProfileIndex, nullptr); - ACTION_ARG(winrt::hstring, Profile, L""); - ACTION_ARG(winrt::guid, SessionId, winrt::guid{}); - ACTION_ARG(bool, AppendCommandLine, false); - ACTION_ARG(Windows::Foundation::IReference, SuppressApplicationTitle, nullptr); - ACTION_ARG(winrt::hstring, ColorScheme); - ACTION_ARG(Windows::Foundation::IReference, Elevate, nullptr); - ACTION_ARG(Windows::Foundation::IReference, ReloadEnvironmentVariables, nullptr); - ACTION_ARG(uint64_t, ContentId); - - static constexpr std::string_view CommandlineKey{ "commandline" }; - static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; - static constexpr std::string_view TabTitleKey{ "tabTitle" }; - static constexpr std::string_view TabColorKey{ "tabColor" }; - static constexpr std::string_view ProfileIndexKey{ "index" }; - static constexpr std::string_view ProfileKey{ "profile" }; - static constexpr std::string_view SessionIdKey{ "sessionId" }; - static constexpr std::string_view AppendCommandLineKey{ "appendCommandLine" }; - static constexpr std::string_view SuppressApplicationTitleKey{ "suppressApplicationTitle" }; - static constexpr std::string_view ColorSchemeKey{ "colorScheme" }; - static constexpr std::string_view ElevateKey{ "elevate" }; - static constexpr std::string_view ReloadEnvironmentVariablesKey{ "reloadEnvironmentVariables" }; - static constexpr std::string_view ContentKey{ "__content" }; - public: + NewTerminalArgs(int32_t& profileIndex) : + _ProfileIndex{ profileIndex } { + NEW_TERMINAL_ARGS(APPEND_ARG_DESCRIPTION); + }; hstring GenerateName() const; hstring ToCommandline() const; @@ -431,7 +426,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::GetValueForKey(json, ColorSchemeKey, args->_ColorScheme); JsonUtils::GetValueForKey(json, ElevateKey, args->_Elevate); JsonUtils::GetValueForKey(json, ReloadEnvironmentVariablesKey, args->_ReloadEnvironmentVariables); - JsonUtils::GetValueForKey(json, ContentKey, args->_ContentId); + JsonUtils::GetValueForKey(json, ContentIdKey, args->_ContentId); return *args; } static Json::Value ToJson(const Model::NewTerminalArgs& val) @@ -453,7 +448,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation JsonUtils::SetValueForKey(json, ColorSchemeKey, args->_ColorScheme); JsonUtils::SetValueForKey(json, ElevateKey, args->_Elevate); JsonUtils::SetValueForKey(json, ReloadEnvironmentVariablesKey, args->_ReloadEnvironmentVariables); - JsonUtils::SetValueForKey(json, ContentKey, args->_ContentId); + JsonUtils::SetValueForKey(json, ContentIdKey, args->_ContentId); return json; } Model::NewTerminalArgs Copy() const @@ -471,6 +466,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation copy->_Elevate = _Elevate; copy->_ReloadEnvironmentVariables = _ReloadEnvironmentVariables; copy->_ContentId = _ContentId; + copy->_argDescriptions = _argDescriptions; return *copy; } size_t Hash() const @@ -589,7 +585,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation NewTabArgs() = default; NewTabArgs(const Model::INewContentArgs& terminalArgs) : _ContentArgs{ terminalArgs } {}; - WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr); + WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{}); public: hstring GenerateName() const; @@ -634,52 +630,52 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } uint32_t GetArgCount() const { - return 2; + return _ContentArgs.as()->GetArgCount(); } - Model::ArgDescription GetArgDescriptionAt(uint32_t /*index*/) const + Model::ArgDescription GetArgDescriptionAt(uint32_t index) const { - return {}; + return _ContentArgs.as()->GetArgDescriptionAt(index); } - IInspectable GetArgAt(uint32_t /*index*/) const + IInspectable GetArgAt(uint32_t index) const { - return nullptr; + return _ContentArgs.as()->GetArgAt(index); } - void SetArgAt(uint32_t /*index*/, IInspectable /*value*/) + void SetArgAt(uint32_t index, IInspectable value) { - throw winrt::hresult_not_implemented(); - } - void SetAllArgsToDefault() - { - throw winrt::hresult_not_implemented(); + _ContentArgs.as()->SetArgAt(index, value); } }; struct SplitPaneArgs : public SplitPaneArgsT { - SplitPaneArgs() = default; + SplitPaneArgs() { + SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION) + }; SplitPaneArgs(SplitType splitMode, SplitDirection direction, float size, const Model::INewContentArgs& terminalArgs) : _SplitMode{ splitMode }, _SplitDirection{ direction }, _SplitSize{ size }, - _ContentArgs{ terminalArgs } {}; + _ContentArgs{ terminalArgs } { + SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION) + }; SplitPaneArgs(SplitDirection direction, float size, const Model::INewContentArgs& terminalArgs) : _SplitDirection{ direction }, _SplitSize{ size }, - _ContentArgs{ terminalArgs } {}; + _ContentArgs{ terminalArgs } { + SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION) + }; SplitPaneArgs(SplitDirection direction, const Model::INewContentArgs& terminalArgs) : _SplitDirection{ direction }, - _ContentArgs{ terminalArgs } {}; + _ContentArgs{ terminalArgs } { + SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION) + }; SplitPaneArgs(SplitType splitMode) : - _SplitMode{ splitMode } {}; + _SplitMode{ splitMode } { + SPLIT_PANE_ARGS(APPEND_ARG_DESCRIPTION) + }; - ACTION_ARG(Model::SplitDirection, SplitDirection, SplitDirection::Automatic); - WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr); - ACTION_ARG(SplitType, SplitMode, SplitType::Manual); - ACTION_ARG(float, SplitSize, 0.5f); - - static constexpr std::string_view SplitKey{ "split" }; - static constexpr std::string_view SplitModeKey{ "splitMode" }; - static constexpr std::string_view SplitSizeKey{ "size" }; + SPLIT_PANE_ARGS(DECLARE_ARGS); + WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{}); public: hstring GenerateName() const; @@ -701,7 +697,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { // LOAD BEARING: Not using make_self here _will_ break you in the future! auto args = winrt::make_self(); - JsonUtils::GetValueForKey(json, SplitKey, args->_SplitDirection); + JsonUtils::GetValueForKey(json, SplitDirectionKey, args->_SplitDirection); JsonUtils::GetValueForKey(json, SplitModeKey, args->_SplitMode); JsonUtils::GetValueForKey(json, SplitSizeKey, args->_SplitSize); if (args->SplitSize() >= 1 || args->SplitSize() <= 0) @@ -721,7 +717,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } const auto args{ get_self(val) }; auto json{ ContentArgsToJson(args->_ContentArgs) }; - JsonUtils::SetValueForKey(json, SplitKey, args->_SplitDirection); + JsonUtils::SetValueForKey(json, SplitDirectionKey, args->_SplitDirection); JsonUtils::SetValueForKey(json, SplitModeKey, args->_SplitMode); JsonUtils::SetValueForKey(json, SplitSizeKey, args->_SplitSize); return json; @@ -733,6 +729,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation copy->_ContentArgs = _ContentArgs.Copy(); copy->_SplitMode = _SplitMode; copy->_SplitSize = _SplitSize; + copy->_argDescriptions = _argDescriptions; return *copy; } size_t Hash() const @@ -746,24 +743,57 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } uint32_t GetArgCount() const { - return 4; + if (const auto newTermArgs = _ContentArgs.try_as()) + { + return newTermArgs->GetArgCount() + gsl::narrow(_argDescriptions.size()); + } + else + { + return gsl::narrow(_argDescriptions.size()); + } } - Model::ArgDescription GetArgDescriptionAt(uint32_t /*index*/) const + Model::ArgDescription GetArgDescriptionAt(uint32_t index) const { - return {}; + const auto additionalArgCount = gsl::narrow(_argDescriptions.size()); + if (index < additionalArgCount) + { + return _argDescriptions.at(index); + } + else + { + return _ContentArgs.as()->GetArgDescriptionAt(index - additionalArgCount); + } } - IInspectable GetArgAt(uint32_t /*index*/) const + IInspectable GetArgAt(uint32_t index) const { + const auto additionalArgCount = gsl::narrow(_argDescriptions.size()); + if (index < additionalArgCount) + { + uint32_t curIndex{ 0 }; + SPLIT_PANE_ARGS(GET_ARG_BY_INDEX); + } + else + { + return _ContentArgs.as()->GetArgAt(index - additionalArgCount); + } return nullptr; } - void SetArgAt(uint32_t /*index*/, IInspectable /*value*/) + void SetArgAt(uint32_t index, IInspectable value) { - throw winrt::hresult_not_implemented(); - } - void SetAllArgsToDefault() - { - throw winrt::hresult_not_implemented(); + const auto additionalArgCount = gsl::narrow(_argDescriptions.size()); + if (index < additionalArgCount) + { + uint32_t curIndex{ 0 }; + SPLIT_PANE_ARGS(SET_ARG_BY_INDEX); + } + else + { + _ContentArgs.as()->SetArgAt(index - additionalArgCount, value); + } } + + private: + std::vector _argDescriptions; }; struct NewWindowArgs : public NewWindowArgsT @@ -771,7 +801,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation NewWindowArgs() = default; NewWindowArgs(const Model::INewContentArgs& terminalArgs) : _ContentArgs{ terminalArgs } {}; - WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, nullptr); + WINRT_PROPERTY(Model::INewContentArgs, ContentArgs, Model::NewTerminalArgs{}); public: hstring GenerateName() const; @@ -816,23 +846,19 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation } uint32_t GetArgCount() const { - return 2; + return _ContentArgs.as()->GetArgCount(); } - Model::ArgDescription GetArgDescriptionAt(uint32_t /*index*/) const + Model::ArgDescription GetArgDescriptionAt(uint32_t index) const { - return {}; + return _ContentArgs.as()->GetArgDescriptionAt(index); } - IInspectable GetArgAt(uint32_t /*index*/) const + IInspectable GetArgAt(uint32_t index) const { - return nullptr; + return _ContentArgs.as()->GetArgAt(index); } - void SetArgAt(uint32_t /*index*/, IInspectable /*value*/) + void SetArgAt(uint32_t index, IInspectable value) { - throw winrt::hresult_not_implemented(); - } - void SetAllArgsToDefault() - { - throw winrt::hresult_not_implemented(); + _ContentArgs.as()->SetArgAt(index, value); } }; @@ -989,10 +1015,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation { throw winrt::hresult_not_implemented(); } - void SetAllArgsToDefault() - { - throw winrt::hresult_not_implemented(); - } }; ACTION_ARGS_STRUCT(AdjustOpacityArgs, ADJUST_OPACITY_ARGS); diff --git a/src/cascadia/TerminalSettingsModel/ActionArgs.idl b/src/cascadia/TerminalSettingsModel/ActionArgs.idl index 01840635c7..9dcbb38874 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgs.idl +++ b/src/cascadia/TerminalSettingsModel/ActionArgs.idl @@ -23,7 +23,6 @@ namespace Microsoft.Terminal.Settings.Model ArgDescription GetArgDescriptionAt(UInt32 index); IInspectable GetArgAt(UInt32 index); void SetArgAt(UInt32 index, Object value); - void SetAllArgsToDefault(); }; interface IActionEventArgs @@ -181,6 +180,11 @@ namespace Microsoft.Terminal.Settings.Model UInt64 ContentId{ get; set; }; String ToCommandline(); + + UInt32 GetArgCount(); + ArgDescription GetArgDescriptionAt(UInt32 index); + IInspectable GetArgAt(UInt32 index); + void SetArgAt(UInt32 index, Object value); }; [default_interface] runtimeclass ActionEventArgs : IActionEventArgs diff --git a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h index 417881639d..5d959c7642 100644 --- a/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h +++ b/src/cascadia/TerminalSettingsModel/ActionArgsMagic.h @@ -77,17 +77,17 @@ struct InitListPlaceholder &&(otherAsUs->_##name == _##name) // getter and setter for each property by index -#define GET_ARG_BY_INDEX(type, name, jsonKey, required, ...) \ - if (index == curIndex++) \ - { \ - if (_##name.has_value()) \ - { \ - return winrt::box_value(_##name.value()); \ - } \ - else \ - { \ - return nullptr; \ - } \ +#define GET_ARG_BY_INDEX(type, name, jsonKey, required, ...) \ + if (index == curIndex++) \ + { \ + if (_##name.has_value()) \ + { \ + return winrt::box_value(_##name.value()); \ + } \ + else \ + { \ + return winrt::box_value(static_cast(__VA_ARGS__)); \ + } \ } #define SET_ARG_BY_INDEX(type, name, jsonKey, required, ...) \ @@ -103,9 +103,6 @@ struct InitListPlaceholder } \ } -#define SET_ARG_TO_DEFAULT(type, name, jsonKey, required, ...) \ - _##name = static_cast(__VA_ARGS__); - // JSON deserialization. If the parameter is required to pass any validation, // add that as the `required` parameter here, as the body of a conditional // EX: For the RESIZE_PANE_ARGS @@ -217,8 +214,38 @@ public: \ { \ uint32_t curIndex{ 0 }; \ argsMacro(SET_ARG_BY_INDEX) \ - } \ - void SetAllArgsToDefault() \ - { \ - argsMacro(SET_ARG_TO_DEFAULT) \ + } + +#define PARTIAL_ACTION_ARG_BODY(className, argsMacro) \ + className(){ argsMacro(APPEND_ARG_DESCRIPTION) }; \ + className( \ + argsMacro(CTOR_PARAMS) InitListPlaceholder = {}) : \ + argsMacro(CTOR_INIT) _placeholder{} { \ + argsMacro(APPEND_ARG_DESCRIPTION) \ + }; \ + argsMacro(DECLARE_ARGS); \ + \ +private: \ + InitListPlaceholder _placeholder; \ + std::vector _argDescriptions; \ + \ +public: \ + uint32_t GetArgCount() const \ + { \ + return gsl::narrow(_argDescriptions.size()); \ + } \ + ArgDescription GetArgDescriptionAt(uint32_t index) const \ + { \ + return _argDescriptions.at(index); \ + } \ + IInspectable GetArgAt(uint32_t index) const \ + { \ + uint32_t curIndex{ 0 }; \ + argsMacro(GET_ARG_BY_INDEX) \ + return nullptr; \ + } \ + void SetArgAt(uint32_t index, IInspectable value) \ + { \ + uint32_t curIndex{ 0 }; \ + argsMacro(SET_ARG_BY_INDEX) \ } diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index 88ac2550d9..dabd494635 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -1074,6 +1074,12 @@ Model::IActionArgs CascadiaSettings::GetEmptyArgsForAction(Model::ShortcutAction return winrt::make(); case Model::ShortcutAction::NextTab: return winrt::make(); + case Model::ShortcutAction::NewTab: + return winrt::make(); + case Model::ShortcutAction::NewWindow: + return winrt::make(); + case Model::ShortcutAction::SplitPane: + return winrt::make(); default: return nullptr; } diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp index 4561badec4..824e9a6cb6 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.cpp +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.cpp @@ -56,6 +56,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Actions DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::ResizeDirection, ResizeDirection); DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::FocusDirection, FocusDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitDirection, SplitDirection); + DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SplitType, SplitType); DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::SettingsTarget, SettingsTarget); DEFINE_ENUM_MAP(Microsoft::Terminal::Settings::Model::MoveTabDirection, MoveTabDirection); DEFINE_ENUM_MAP(Microsoft::Terminal::Control::ScrollToMarkDirection, ScrollToMarkDirection); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.h b/src/cascadia/TerminalSettingsModel/EnumMappings.h index 3b522273e9..83d183b344 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.h +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.h @@ -53,6 +53,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation // Actions static winrt::Windows::Foundation::Collections::IMap ResizeDirection(); static winrt::Windows::Foundation::Collections::IMap FocusDirection(); + static winrt::Windows::Foundation::Collections::IMap SplitDirection(); + static winrt::Windows::Foundation::Collections::IMap SplitType(); static winrt::Windows::Foundation::Collections::IMap SettingsTarget(); static winrt::Windows::Foundation::Collections::IMap MoveTabDirection(); static winrt::Windows::Foundation::Collections::IMap ScrollToMarkDirection(); diff --git a/src/cascadia/TerminalSettingsModel/EnumMappings.idl b/src/cascadia/TerminalSettingsModel/EnumMappings.idl index e97e095c6b..f4c8d2a318 100644 --- a/src/cascadia/TerminalSettingsModel/EnumMappings.idl +++ b/src/cascadia/TerminalSettingsModel/EnumMappings.idl @@ -35,6 +35,8 @@ namespace Microsoft.Terminal.Settings.Model // Actions static Windows.Foundation.Collections.IMap ResizeDirection { get; }; static Windows.Foundation.Collections.IMap FocusDirection { get; }; + static Windows.Foundation.Collections.IMap SplitDirection { get; }; + static Windows.Foundation.Collections.IMap SplitType { get; }; static Windows.Foundation.Collections.IMap SettingsTarget { get; }; static Windows.Foundation.Collections.IMap MoveTabDirection { get; }; static Windows.Foundation.Collections.IMap ScrollToMarkDirection { get; };