diff --git a/src/cascadia/TerminalApp/CommandPalette.cpp b/src/cascadia/TerminalApp/CommandPalette.cpp index 6fac2d35d..33d32defe 100644 --- a/src/cascadia/TerminalApp/CommandPalette.cpp +++ b/src/cascadia/TerminalApp/CommandPalette.cpp @@ -271,16 +271,17 @@ namespace winrt::TerminalApp::implementation }; // Method Description: - // - Update our list of filtered actions to reflect the current contents of + // - Produce a list of filtered actions to reflect the current contents of // the input box. For more details on which commands will be displayed, // see `_getWeight`. // Arguments: - // - + // - A collection that will receive the filtered actions // Return Value: // - - void CommandPalette::_updateFilteredActions() + std::vector CommandPalette::_collectFilteredActions() { - _filteredActions.Clear(); + std::vector actions; + auto searchText = _searchBox().Text(); const bool addAll = searchText.empty(); @@ -303,10 +304,10 @@ namespace winrt::TerminalApp::implementation for (auto action : sortedCommands) { - _filteredActions.Append(action); + actions.push_back(action); } - return; + return actions; } // Here, there was some filter text. @@ -343,7 +344,56 @@ namespace winrt::TerminalApp::implementation { auto top = heap.top(); heap.pop(); - _filteredActions.Append(top.command); + actions.push_back(top.command); + } + + return actions; + } + + // Method Description: + // - Update our list of filtered actions to reflect the current contents of + // the input box. For more details on which commands will be displayed, + // see `_getWeight`. + // Arguments: + // - + // Return Value: + // - + void CommandPalette::_updateFilteredActions() + { + auto actions = _collectFilteredActions(); + + // Make _filteredActions look identical to actions, using only Insert and Remove. + // This allows WinUI to nicely animate the ListView as it changes. + for (uint32_t i = 0; i < _filteredActions.Size() && i < actions.size(); i++) + { + for (uint32_t j = i; j < _filteredActions.Size(); j++) + { + if (_filteredActions.GetAt(j) == actions[i]) + { + for (uint32_t k = i; k < j; k++) + { + _filteredActions.RemoveAt(i); + } + break; + } + } + + if (_filteredActions.GetAt(i) != actions[i]) + { + _filteredActions.InsertAt(i, actions[i]); + } + } + + // Remove any extra trailing items from the destination + while (_filteredActions.Size() > actions.size()) + { + _filteredActions.RemoveAtEnd(); + } + + // Add any extra trailing items from the source + while (_filteredActions.Size() < actions.size()) + { + _filteredActions.Append(actions[_filteredActions.Size()]); } } diff --git a/src/cascadia/TerminalApp/CommandPalette.h b/src/cascadia/TerminalApp/CommandPalette.h index 2d3960705..a14466f4f 100644 --- a/src/cascadia/TerminalApp/CommandPalette.h +++ b/src/cascadia/TerminalApp/CommandPalette.h @@ -37,6 +37,7 @@ namespace winrt::TerminalApp::implementation void _selectNextItem(const bool moveDown); void _updateFilteredActions(); + std::vector _collectFilteredActions(); static int _getWeight(const winrt::hstring& searchText, const winrt::hstring& name); void _close();