Skip to content

Commit

Permalink
Teach the command palette to clamp its indices on page up/down (#8190)
Browse files Browse the repository at this point in the history
This commit will teach CommandPalette to clamp the scroll page up and
scroll page down navigation so as to not wrap.

Closes #8189

(cherry picked from commit 624d07f)
  • Loading branch information
Don-Vito authored and DHowett committed Nov 9, 2020
1 parent 89191f8 commit 744631a
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 33 deletions.
101 changes: 71 additions & 30 deletions src/cascadia/TerminalApp/CommandPalette.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,48 +120,87 @@ namespace winrt::TerminalApp::implementation
}

// Method Description:
// - Scrolls the focus up or down the list of commands.
// - Scroll the command palette to the specified index
// Arguments:
// - pageDown: if true, we're attempting to move to last visible item in the
// list. Otherwise, we're attempting to move to first visible item.
// - index within a list view of commands
// Return Value:
// - <none>
void CommandPalette::ScrollDown(const bool pageDown)
void CommandPalette::_scrollToIndex(uint32_t index)
{
auto numItems = _filteredActionsView().Items().Size();

if (numItems == 0)
{
// if the list is empty no need to scroll
return;
}

auto clampedIndex = std::clamp<int32_t>(index, 0, numItems - 1);
_filteredActionsView().SelectedIndex(clampedIndex);
_filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem());
}

// Method Description:
// - Computes the number of visible commands
// Arguments:
// - <none>
// Return Value:
// - the approximate number of items visible in the list (in other words the size of the page)
uint32_t CommandPalette::_getNumVisibleItems()
{
const auto container = _filteredActionsView().ContainerFromIndex(0);
const auto item = container.try_as<winrt::Windows::UI::Xaml::Controls::ListViewItem>();
const auto itemHeight = ::base::saturated_cast<int>(item.ActualHeight());
const auto listHeight = ::base::saturated_cast<int>(_filteredActionsView().ActualHeight());
const int numVisibleItems = listHeight / itemHeight;
return listHeight / itemHeight;
}

// Method Description:
// - Scrolls the focus one page up the list of commands.
// Arguments:
// - <none>
// Return Value:
// - <none>
void CommandPalette::ScrollPageUp()
{
auto selected = _filteredActionsView().SelectedIndex();
const int numItems = ::base::saturated_cast<int>(_filteredActionsView().Items().Size());
auto numVisibleItems = _getNumVisibleItems();
_scrollToIndex(selected - numVisibleItems);
}

const auto newIndex = ((numItems + selected + (pageDown ? numVisibleItems : -numVisibleItems)) % numItems);
_filteredActionsView().SelectedIndex(newIndex);
_filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem());
// Method Description:
// - Scrolls the focus one page down the list of commands.
// Arguments:
// - <none>
// Return Value:
// - <none>
void CommandPalette::ScrollPageDown()
{
auto selected = _filteredActionsView().SelectedIndex();
auto numVisibleItems = _getNumVisibleItems();
_scrollToIndex(selected + numVisibleItems);
}

// Method Description:
// - Moves the focus either to top item or end item in the list of commands.
// - Moves the focus to the top item in the list of commands.
// Arguments:
// - end: if true, we're attempting to move to last item in the
// list. Otherwise, we're attempting to move to first item.
// Depends on the pageUpDown argument.
// - <none>
// Return Value:
// - <none>
void CommandPalette::GoEnd(const bool end)
void CommandPalette::ScrollToTop()
{
const auto lastIndex = ::base::saturated_cast<int>(_filteredActionsView().Items().Size() - 1);
if (end)
{
_filteredActionsView().SelectedIndex(lastIndex);
}
else
{
_filteredActionsView().SelectedIndex(0);
}
_filteredActionsView().ScrollIntoView(_filteredActionsView().SelectedItem());
_scrollToIndex(0);
}

// Method Description:
// - Moves the focus to the bottom item in the list of commands.
// Arguments:
// - <none>
// Return Value:
// - <none>
void CommandPalette::ScrollToBottom()
{
_scrollToIndex(_filteredActionsView().Items().Size() - 1);
}

// Method Description:
Expand Down Expand Up @@ -242,24 +281,26 @@ namespace winrt::TerminalApp::implementation
}
else if (key == VirtualKey::PageUp)
{
// Action Mode: Move focus to the previous item in the list.
ScrollDown(false);
// Action Mode: Move focus to the first visible item in the list.
ScrollPageUp();
e.Handled(true);
}
else if (key == VirtualKey::PageDown)
{
// Action Mode: Move focus to the previous item in the list.
ScrollDown(true);
// Action Mode: Move focus to the last visible item in the list.
ScrollPageDown();
e.Handled(true);
}
else if (key == VirtualKey::Home)
{
GoEnd(false);
// Action Mode: Move focus to the first item in the list.
ScrollToTop();
e.Handled(true);
}
else if (key == VirtualKey::End)
{
GoEnd(true);
// Action Mode: Move focus to the last item in the list.
ScrollToBottom();
e.Handled(true);
}
else if (key == VirtualKey::Enter)
Expand Down
10 changes: 7 additions & 3 deletions src/cascadia/TerminalApp/CommandPalette.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ namespace winrt::TerminalApp::implementation

void SelectNextItem(const bool moveDown);

void ScrollDown(const bool pageDown);

void GoEnd(const bool end);
void ScrollPageUp();
void ScrollPageDown();
void ScrollToTop();
void ScrollToBottom();

// Tab Switcher
void EnableTabSwitcherMode(const bool searchMode, const uint32_t startIdx);
Expand Down Expand Up @@ -103,6 +104,9 @@ namespace winrt::TerminalApp::implementation
void _dispatchCommand(const TerminalApp::Command& command);
void _dispatchCommandline();
void _dismissPalette();

void _scrollToIndex(uint32_t index);
uint32_t _getNumVisibleItems();
};
}

Expand Down

0 comments on commit 744631a

Please sign in to comment.