Add home/end/pageup/pagedown support to listview

This commit is contained in:
Magnus Norddahl 2025-07-28 23:17:49 +02:00
commit 2f9e286dc7
2 changed files with 57 additions and 8 deletions

View file

@ -36,6 +36,8 @@ protected:
void OnGeometryChanged() override;
void OnScrollbarScroll();
static double getItemHeight();
Scrollbar* scrollbar = nullptr;
std::vector<std::vector<std::string>> items;

View file

@ -66,7 +66,7 @@ void ListView::AddItem(const std::string& text, int index, int column)
{
items.push_back(newEntry);
}
scrollbar->SetRanges(GetHeight(), items.size() * 20.0);
scrollbar->SetRanges(GetHeight(), items.size() * getItemHeight());
Update();
}
@ -91,7 +91,7 @@ void ListView::RemoveItem(int index)
SetSelectedItem(0);
items.erase(items.begin() + index);
scrollbar->SetRanges(GetHeight(), items.size() * 20.0);
scrollbar->SetRanges(GetHeight(), items.size() * getItemHeight());
Update();
}
@ -111,9 +111,14 @@ void ListView::SetSelectedItem(int index)
}
}
double ListView::getItemHeight()
{
return 20.0;
}
void ListView::ScrollToItem(int index)
{
double itemHeight = 20.0;
double itemHeight = getItemHeight();
double y = itemHeight * index;
if (y < scrollbar->GetPosition())
{
@ -136,7 +141,7 @@ void ListView::OnGeometryChanged()
double h = GetHeight();
double sw = scrollbar->GetPreferredWidth();
scrollbar->SetFrameGeometry(Rect::xywh(w - sw, 0.0, sw, h));
scrollbar->SetRanges(h, items.size() * 20.0);
scrollbar->SetRanges(h, items.size() * getItemHeight());
}
void ListView::OnPaint(Canvas* canvas)
@ -144,7 +149,7 @@ void ListView::OnPaint(Canvas* canvas)
double y = -scrollbar->GetPosition();
double x = 2.0;
double w = GetWidth() - scrollbar->GetPreferredWidth() - 2.0;
double h = 20.0;
double h = getItemHeight();
Colorf textColor = GetStyleColor("color");
Colorf selectionColor = GetStyleColor("selection-color");
@ -182,7 +187,7 @@ bool ListView::OnMouseDown(const Point& pos, InputKey key)
if (key == InputKey::LeftMouse)
{
int index = (int)((pos.y - 5.0 + scrollbar->GetPosition()) / 20.0);
int index = (int)((pos.y - 5.0 + scrollbar->GetPosition()) / getItemHeight());
if (index >= 0 && (size_t)index < items.size())
{
SetSelectedItem(index);
@ -205,11 +210,11 @@ bool ListView::OnMouseWheel(const Point& pos, InputKey key)
{
if (key == InputKey::MouseWheelUp)
{
scrollbar->SetPosition(std::max(scrollbar->GetPosition() - 20.0, 0.0));
scrollbar->SetPosition(std::max(scrollbar->GetPosition() - getItemHeight(), 0.0));
}
else if (key == InputKey::MouseWheelDown)
{
scrollbar->SetPosition(std::min(scrollbar->GetPosition() + 20.0, scrollbar->GetMax()));
scrollbar->SetPosition(std::min(scrollbar->GetPosition() + getItemHeight(), scrollbar->GetMax()));
}
return true;
}
@ -236,4 +241,46 @@ void ListView::OnKeyDown(InputKey key)
{
Activate();
}
else if (key == InputKey::Home)
{
if (selectedItem > 0)
{
SetSelectedItem(0);
}
ScrollToItem(selectedItem);
}
else if (key == InputKey::End)
{
if (selectedItem + 1 < (int)items.size())
{
SetSelectedItem((int)items.size() - 1);
}
ScrollToItem(selectedItem);
}
else if (key == InputKey::PageUp)
{
double h = GetHeight();
if (h <= 0.0 || items.empty())
return;
int itemsPerPage = (int)std::max(std::round(h / getItemHeight()), 1.0);
int nextItem = std::max(selectedItem - itemsPerPage, 0);
if (nextItem != selectedItem)
{
SetSelectedItem(nextItem);
ScrollToItem(selectedItem);
}
}
else if (key == InputKey::PageDown)
{
double h = GetHeight();
if (h <= 0.0 || items.empty())
return;
int itemsPerPage = (int)std::max(std::round(h / getItemHeight()), 1.0);
int prevItem = std::min(selectedItem + itemsPerPage, (int)items.size() - 1);
if (prevItem != selectedItem)
{
SetSelectedItem(prevItem);
ScrollToItem(selectedItem);
}
}
}