From 56bf598d0fbba3f959739ba532c31eea0fd214ff Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 13 Oct 2020 13:23:49 -0500 Subject: [PATCH 1/3] turns out all of this is terrible --- src/cascadia/TerminalApp/CommandPalette.cpp | 63 ++++++++----- src/cascadia/TerminalApp/CommandPalette.h | 3 +- src/cascadia/TerminalApp/CommandPalette.idl | 3 +- src/cascadia/TerminalApp/CommandPalette.xaml | 89 +++++++++++-------- .../Resources/en-US/Resources.resw | 62 +++++++------ 5 files changed, 128 insertions(+), 92 deletions(-) diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 3a5a5ad6195..bf399e116f5 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -213,33 +213,22 @@ namespace winrt::TerminalApp::implementation } else if (key == VirtualKey::Escape) { - // Action, TabSearch, TabSwitch Mode: Dismiss the palette if the + // Commandline, TabSearch, TabSwitch Mode: Dismiss the palette if the // text is empty, otherwise clear the search string. - if (_currentMode != CommandPaletteMode::CommandlineMode) - { - if (_searchBox().Text().empty()) - { - _dismissPalette(); - } - else - { - _searchBox().Text(L""); - } - } - else if (_currentMode == CommandPaletteMode::CommandlineMode) + if (_currentMode != CommandPaletteMode::ActionMode) { const auto currentInput = _getPostPrefixInput(); if (currentInput.empty()) { - // The user's only input "> " so far. We should just dismiss - // the palette. This is like dismissing the Action mode with + // The user has only input "> " so far. We should just dismiss + // the palette. This is like dismissing the commandline mode with // empty input. _dismissPalette(); } else { // Clear out the current input. We'll leave a ">" in the - // input (to stay in commandline mode), and a leading space + // input (to stay in action mode), and a leading space // (if they currently had one). const bool hasLeadingSpace = (_searchBox().Text().size()) - (currentInput.size()) > 1; _searchBox().Text(hasLeadingSpace ? L"> " : L">"); @@ -249,6 +238,17 @@ namespace winrt::TerminalApp::implementation _searchBox().Select(_searchBox().Text().size(), 0); } } + else if (_currentMode == CommandPaletteMode::ActionMode) + { + if (_searchBox().Text().empty()) + { + _dismissPalette(); + } + else + { + _searchBox().Text(L""); + } + } e.Handled(true); } @@ -582,19 +582,28 @@ namespace winrt::TerminalApp::implementation _updateFilteredActions(); _filteredActionsView().SelectedIndex(0); - _noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible); + if (_currentMode == CommandPaletteMode::ActionMode) + { + winrt::hstring searchText{ _getPostPrefixInput() }; + FakePlaceholderText(searchText.empty() ? RS_(L"CmdPalActionPrompt") : L""); + } + + if (_currentMode == CommandPaletteMode::CommandlineMode || _currentMode == CommandPaletteMode::ActionMode) + { + _noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible); + } } void CommandPalette::_evaluatePrefix() { - auto newMode = CommandPaletteMode::ActionMode; + auto newMode = CommandPaletteMode::CommandlineMode; auto inputText = _searchBox().Text(); if (inputText.size() > 0) { if (inputText[0] == L'>') { - newMode = CommandPaletteMode::CommandlineMode; + newMode = CommandPaletteMode::ActionMode; } } @@ -652,20 +661,28 @@ namespace winrt::TerminalApp::implementation case CommandPaletteMode::TabSearchMode: case CommandPaletteMode::TabSwitchMode: { - SearchBoxText(RS_(L"TabSwitcher_SearchBoxText")); + SearchBoxPlaceholderText(RS_(L"TabSwitcher_SearchBoxText")); + FakePlaceholderText(L""); NoMatchesText(RS_(L"TabSwitcher_NoMatchesText")); ControlName(RS_(L"TabSwitcherControlName")); + _searchBox().Text(L""); break; } case CommandPaletteMode::CommandlineMode: - NoMatchesText(RS_(L"CmdPalCommandlinePrompt")); + SearchBoxPlaceholderText(RS_(L"CmdPalCommandlinePrompt")); + FakePlaceholderText(L""); + NoMatchesText(L""); ControlName(RS_(L"CommandPaletteControlName")); + _searchBox().Text(L""); break; case CommandPaletteMode::ActionMode: default: - SearchBoxText(RS_(L"CommandPalette_SearchBox/PlaceholderText")); + SearchBoxPlaceholderText(L""); + FakePlaceholderText(RS_(L"CmdPalActionPrompt")); NoMatchesText(RS_(L"CommandPalette_NoMatchesText/Text")); ControlName(RS_(L"CommandPaletteControlName")); + _searchBox().Text(L">"); + _searchBox().Select(_searchBox().Text().size(), 0); break; } } @@ -717,7 +734,7 @@ namespace winrt::TerminalApp::implementation { std::vector actions; - auto searchText = _searchBox().Text(); + winrt::hstring searchText{ _getPostPrefixInput() }; const bool addAll = searchText.empty(); auto commandsToFilter = _commandsToFilter(); diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index 8ec262519a2..7cd963ca22a 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -39,7 +39,8 @@ namespace winrt::TerminalApp::implementation WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers); - OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, FakePlaceholderText, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers); diff --git a/src/cascadia/TerminalApp/CommandPalette.idl b/src/cascadia/TerminalApp/CommandPalette.idl index f938515354f..7a61e4e1a97 100644 --- a/src/cascadia/TerminalApp/CommandPalette.idl +++ b/src/cascadia/TerminalApp/CommandPalette.idl @@ -11,7 +11,8 @@ namespace TerminalApp CommandPalette(); String NoMatchesText { get; }; - String SearchBoxText { get; }; + String SearchBoxPlaceholderText { get; }; + String FakePlaceholderText { get; }; String ControlName { get; }; String ParentCommandName { get; }; diff --git a/src/cascadia/TerminalApp/CommandPalette.xaml b/src/cascadia/TerminalApp/CommandPalette.xaml index 1a3808cface..198c0a3ff15 100644 --- a/src/cascadia/TerminalApp/CommandPalette.xaml +++ b/src/cascadia/TerminalApp/CommandPalette.xaml @@ -8,8 +8,8 @@ the MIT License. See LICENSE in the project root for license information. --> xmlns:mux="using:Microsoft.UI.Xaml.Controls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)" - xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model" + xmlns:Windows10version1903="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract, 8)" + xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model" TabNavigation="Cycle" IsTabStop="True" AllowFocusOnInteraction="True" @@ -135,27 +135,27 @@ the MIT License. See LICENSE in the project root for license information. --> to receive clicks _anywhere_ in its bounds. --> + x:Name="_shadowBackdrop" + Background="Transparent" + Grid.Column="0" + Grid.Row="0" + Grid.ColumnSpan="3" + Grid.RowSpan="2" + HorizontalAlignment="Stretch" + VerticalAlignment="Stretch"> + x:Name="_backdrop" + Style="{ThemeResource CommandPaletteBackground}" + CornerRadius="{ThemeResource ControlCornerRadius}" + PointerPressed="_backdropPointerPressed" + Margin="8" + Grid.Column="1" + Grid.Row="0" + Windows10version1903:Shadow="{StaticResource CommandPaletteShadow}" + HorizontalAlignment="Stretch" + VerticalAlignment="Top"> @@ -164,15 +164,28 @@ the MIT License. See LICENSE in the project root for license information. --> + Grid.Row="0" + x:Name="_searchBox" + Margin="8" + IsSpellCheckEnabled="False" + TextChanged="_filterTextChanged" + PlaceholderText="{x:Bind SearchBoxPlaceholderText, Mode=OneWay}" + Text=""> + + + + Grid.Row="2" + x:Name="_filteredActionsView" + HorizontalAlignment="Stretch" + VerticalAlignment="Stretch" + SelectionMode="Single" + CanReorderItems="False" + AllowDrop="False" + IsItemClickEnabled="True" + ItemClick="_listItemClicked" + PreviewKeyDown="_keyDownHandler" + ItemsSource="{x:Bind FilteredActions}"> diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 893f1cd048b..41940e076f5 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - @@ -379,7 +379,8 @@ Warning - Type a command name... + Enter a wt commandline to run + {Locked="wt"} No matching commands @@ -396,6 +397,9 @@ No matching tab name + + Type a command name... + Enter a wt commandline to run {Locked="wt"} @@ -457,4 +461,4 @@ Cancel - \ No newline at end of file + From 0989c1188456f0415e0dc3a8abe450b92429112a Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 15 Oct 2020 11:58:47 -0500 Subject: [PATCH 2/3] now this is what I'm talking about --- src/cascadia/TerminalApp/CommandPalette.cpp | 112 ++++++++----------- src/cascadia/TerminalApp/CommandPalette.h | 6 +- src/cascadia/TerminalApp/CommandPalette.idl | 2 +- src/cascadia/TerminalApp/CommandPalette.xaml | 12 +- 4 files changed, 59 insertions(+), 73 deletions(-) diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index bf399e116f5..337899a1f68 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -213,41 +213,27 @@ namespace winrt::TerminalApp::implementation } else if (key == VirtualKey::Escape) { - // Commandline, TabSearch, TabSwitch Mode: Dismiss the palette if the - // text is empty, otherwise clear the search string. - if (_currentMode != CommandPaletteMode::ActionMode) + // Dismiss the palette if the text is empty, otherwise clear the + // search string. + if (_searchBox().Text().empty()) { - const auto currentInput = _getPostPrefixInput(); - if (currentInput.empty()) - { - // The user has only input "> " so far. We should just dismiss - // the palette. This is like dismissing the commandline mode with - // empty input. - _dismissPalette(); - } - else - { - // Clear out the current input. We'll leave a ">" in the - // input (to stay in action mode), and a leading space - // (if they currently had one). - const bool hasLeadingSpace = (_searchBox().Text().size()) - (currentInput.size()) > 1; - _searchBox().Text(hasLeadingSpace ? L"> " : L">"); - - // This will conveniently move the cursor to the end of the - // text input for us. - _searchBox().Select(_searchBox().Text().size(), 0); - } + _dismissPalette(); } - else if (_currentMode == CommandPaletteMode::ActionMode) + else { - if (_searchBox().Text().empty()) - { - _dismissPalette(); - } - else - { - _searchBox().Text(L""); - } + _searchBox().Text(L""); + } + + e.Handled(true); + } + else if (key == VirtualKey::Back) + { + // If the last filter text was empty, and we're backspacing from + // that state, then the user "backspaced" the virtual '>' we're + // using as the action mode indicator. Switch into commandline mode. + if (_searchBox().Text().empty() && _lastFilterTextWasEmpty && _currentMode == CommandPaletteMode::ActionMode) + { + _switchToMode(CommandPaletteMode::CommandlineMode); } e.Handled(true); @@ -480,18 +466,13 @@ namespace winrt::TerminalApp::implementation } } } - // Method Description: - // - Get all the input text in _searchBox that follows the prefix character - // and any whitespace following that prefix character. This can be used in - // commandline mode to get all the useful input that the user input after - // the leading ">" prefix. - // - Note that this will behave unexpectedly in Action Mode. + // - Get all the input text in _searchBox that follows any leading spaces. // Arguments: // - // Return Value: - // - the string of input following the prefix character. - std::wstring CommandPalette::_getPostPrefixInput() + // - the string of input following any number of leading spaces + std::wstring CommandPalette::_getTrimmedInput() { const std::wstring input{ _searchBox().Text() }; if (input.empty()) @@ -499,17 +480,15 @@ namespace winrt::TerminalApp::implementation return input; } - const auto rawCmdline{ input.substr(1) }; - // Trim leading whitespace - const auto firstNonSpace = rawCmdline.find_first_not_of(L" "); + const auto firstNonSpace = input.find_first_not_of(L" "); if (firstNonSpace == std::wstring::npos) { // All the following characters are whitespace. return L""; } - return rawCmdline.substr(firstNonSpace); + return input.substr(firstNonSpace); } // Method Description: @@ -520,12 +499,11 @@ namespace winrt::TerminalApp::implementation // - void CommandPalette::_dispatchCommandline() { - const auto input = _getPostPrefixInput(); - if (input.empty()) + auto cmdline{ _getTrimmedInput() }; + if (cmdline.empty()) { return; } - winrt::hstring cmdline{ input }; // Build the ExecuteCommandline action from the values we've parsed on the commandline. ExecuteCommandlineArgs args{ cmdline }; @@ -574,31 +552,38 @@ namespace winrt::TerminalApp::implementation void CommandPalette::_filterTextChanged(IInspectable const& /*sender*/, Windows::UI::Xaml::RoutedEventArgs const& /*args*/) { - if (_currentMode == CommandPaletteMode::CommandlineMode || _currentMode == CommandPaletteMode::ActionMode) + if (_currentMode == CommandPaletteMode::CommandlineMode) { _evaluatePrefix(); } + // We're setting _lastFilterTextWasEmpty here, because if the user tries + // to backspace the last character in the input, the Backspace KeyDown + // event will fire _before_ _filterTextChanged does. Updating the value + // here will ensure that we can check this case appropriately. + _lastFilterTextWasEmpty = _searchBox().Text().empty(); + _updateFilteredActions(); _filteredActionsView().SelectedIndex(0); - if (_currentMode == CommandPaletteMode::ActionMode) + if (_currentMode == CommandPaletteMode::TabSearchMode || _currentMode == CommandPaletteMode::ActionMode) { - winrt::hstring searchText{ _getPostPrefixInput() }; - FakePlaceholderText(searchText.empty() ? RS_(L"CmdPalActionPrompt") : L""); + _noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible); } - - if (_currentMode == CommandPaletteMode::CommandlineMode || _currentMode == CommandPaletteMode::ActionMode) + else { - _noMatchesText().Visibility(_filteredActions.Size() > 0 ? Visibility::Collapsed : Visibility::Visible); + _noMatchesText().Visibility(Visibility::Collapsed); } } void CommandPalette::_evaluatePrefix() { + // This will take you from commandline mode, into action mode. The + // backspace handler in _keyDownHandler will handle taking us from + // action mode to commandline mode. auto newMode = CommandPaletteMode::CommandlineMode; - auto inputText = _searchBox().Text(); + auto inputText = _getTrimmedInput(); if (inputText.size() > 0) { if (inputText[0] == L'>') @@ -609,6 +594,7 @@ namespace winrt::TerminalApp::implementation if (newMode != _currentMode) { + //_switchToMode will remove the '>' character from the input. _switchToMode(newMode); } } @@ -653,6 +639,8 @@ namespace winrt::TerminalApp::implementation } } + _searchBox().Text(L""); + _searchBox().Select(_searchBox().Text().size(), 0); // Leaving this block of code outside the above if-statement // guarantees that the correct text is shown for the mode // whenever _switchToMode is called. @@ -662,27 +650,23 @@ namespace winrt::TerminalApp::implementation case CommandPaletteMode::TabSwitchMode: { SearchBoxPlaceholderText(RS_(L"TabSwitcher_SearchBoxText")); - FakePlaceholderText(L""); NoMatchesText(RS_(L"TabSwitcher_NoMatchesText")); ControlName(RS_(L"TabSwitcherControlName")); - _searchBox().Text(L""); + PrefixCharacter(L""); break; } case CommandPaletteMode::CommandlineMode: SearchBoxPlaceholderText(RS_(L"CmdPalCommandlinePrompt")); - FakePlaceholderText(L""); NoMatchesText(L""); ControlName(RS_(L"CommandPaletteControlName")); - _searchBox().Text(L""); + PrefixCharacter(L""); break; case CommandPaletteMode::ActionMode: default: - SearchBoxPlaceholderText(L""); - FakePlaceholderText(RS_(L"CmdPalActionPrompt")); + SearchBoxPlaceholderText(RS_(L"CmdPalActionPrompt")); NoMatchesText(RS_(L"CommandPalette_NoMatchesText/Text")); ControlName(RS_(L"CommandPaletteControlName")); - _searchBox().Text(L">"); - _searchBox().Select(_searchBox().Text().size(), 0); + PrefixCharacter(L">"); break; } } @@ -734,7 +718,7 @@ namespace winrt::TerminalApp::implementation { std::vector actions; - winrt::hstring searchText{ _getPostPrefixInput() }; + winrt::hstring searchText{ _getTrimmedInput() }; const bool addAll = searchText.empty(); auto commandsToFilter = _commandsToFilter(); diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index 7cd963ca22a..36bb95704c1 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -40,7 +40,7 @@ namespace winrt::TerminalApp::implementation WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, NoMatchesText, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, SearchBoxPlaceholderText, _PropertyChangedHandlers); - OBSERVABLE_GETSET_PROPERTY(winrt::hstring, FakePlaceholderText, _PropertyChangedHandlers); + OBSERVABLE_GETSET_PROPERTY(winrt::hstring, PrefixCharacter, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ControlName, _PropertyChangedHandlers); OBSERVABLE_GETSET_PROPERTY(winrt::hstring, ParentCommandName, _PropertyChangedHandlers); @@ -56,6 +56,8 @@ namespace winrt::TerminalApp::implementation Windows::Foundation::Collections::IVector _commandsToFilter(); + bool _lastFilterTextWasEmpty{ true }; + void _filterTextChanged(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args); void _previewKeyDownHandler(Windows::Foundation::IInspectable const& sender, @@ -85,8 +87,8 @@ namespace winrt::TerminalApp::implementation CommandPaletteMode _currentMode; void _switchToMode(CommandPaletteMode mode); + std::wstring _getTrimmedInput(); void _evaluatePrefix(); - std::wstring _getPostPrefixInput(); Microsoft::Terminal::TerminalControl::IKeyBindings _bindings; diff --git a/src/cascadia/TerminalApp/CommandPalette.idl b/src/cascadia/TerminalApp/CommandPalette.idl index 7a61e4e1a97..256cff7758c 100644 --- a/src/cascadia/TerminalApp/CommandPalette.idl +++ b/src/cascadia/TerminalApp/CommandPalette.idl @@ -12,7 +12,7 @@ namespace TerminalApp String NoMatchesText { get; }; String SearchBoxPlaceholderText { get; }; - String FakePlaceholderText { get; }; + String PrefixCharacter { get; }; String ControlName { get; }; String ParentCommandName { get; }; diff --git a/src/cascadia/TerminalApp/CommandPalette.xaml b/src/cascadia/TerminalApp/CommandPalette.xaml index 198c0a3ff15..236500a84eb 100644 --- a/src/cascadia/TerminalApp/CommandPalette.xaml +++ b/src/cascadia/TerminalApp/CommandPalette.xaml @@ -167,6 +167,7 @@ the MIT License. See LICENSE in the project root for license information. --> Grid.Row="0" x:Name="_searchBox" Margin="8" + Padding="18,8,8,8" IsSpellCheckEnabled="False" TextChanged="_filterTextChanged" PlaceholderText="{x:Bind SearchBoxPlaceholderText, Mode=OneWay}" @@ -175,14 +176,13 @@ the MIT License. See LICENSE in the project root for license information. --> From 547fc913cb2a0018cb666d808fac9082cc37c0d6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 15 Oct 2020 16:19:31 -0500 Subject: [PATCH 3/3] revert resources changes --- src/cascadia/TerminalApp/CommandPalette.cpp | 2 +- .../Resources/en-US/Resources.resw | 62 +++++++++---------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 337899a1f68..3e8f57c7f3e 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -663,7 +663,7 @@ namespace winrt::TerminalApp::implementation break; case CommandPaletteMode::ActionMode: default: - SearchBoxPlaceholderText(RS_(L"CmdPalActionPrompt")); + SearchBoxPlaceholderText(RS_(L"CommandPalette_SearchBox/PlaceholderText")); NoMatchesText(RS_(L"CommandPalette_NoMatchesText/Text")); ControlName(RS_(L"CommandPaletteControlName")); PrefixCharacter(L">"); diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 41940e076f5..893f1cd048b 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -1,17 +1,17 @@  - @@ -379,8 +379,7 @@ Warning - Enter a wt commandline to run - {Locked="wt"} + Type a command name... No matching commands @@ -397,9 +396,6 @@ No matching tab name - - Type a command name... - Enter a wt commandline to run {Locked="wt"} @@ -461,4 +457,4 @@ Cancel - + \ No newline at end of file