Skip to content

Commit

Permalink
[GuiScrollbar] Scrollbar limits fixed (#2022)
Browse files Browse the repository at this point in the history
* [GuiScrollbar] Move copy/paste updates to onDraw, persist values

* [GuiScrollbar] Prevent draggable bar from dropping to below bottom arrow button

* [GuiScrollbar] Enable full range on large lists

* Problems with range calculations prevented access to full range in large lists
* These adjustments allow drag-scrolling to the end without any slop
* Tested on:
** Comms smaller than the window
** Comms larger than the window
** A log smaller than the window
** A log with 10,000 entries

---------

Co-authored-by: oznogon <[email protected]>
  • Loading branch information
csibbitt and oznogon authored Oct 16, 2023
1 parent 2e8ecfc commit 6eb8449
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 30 deletions.
44 changes: 14 additions & 30 deletions src/gui/gui2_scrollbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,21 @@ void GuiScrollbar::onDraw(sp::RenderTarget& renderer)

renderer.drawStretched(rect, back.texture, back.color);

int range = (max_value - min_value);
float arrow_size = rect.size.x / 2.0f;
float move_height = (rect.size.y - arrow_size * 2);
float bar_size = move_height * value_size / range;
if (bar_size > move_height)
bar_size = move_height;
renderer.drawStretched(sp::Rect(rect.position.x, rect.position.y + arrow_size + move_height * getValue() / range, rect.size.x, bar_size), front.texture, front.color);
// Update the bar's range, size, and draggable bar size.
range = max_value - min_value - value_size;
arrow_size = rect.size.x / 2.0f;
move_height = rect.size.y - arrow_size * 2;
// Clamp the size of the draggable bar to no less than 20px.
bar_size = std::clamp(move_height * value_size / (range + value_size), 20.0F, move_height);
// Set the bottom of the draggable bar no lower than the top of the bottom arrow.
const float bar_y = std::min((rect.position.y + arrow_size + (move_height - bar_size) * getValue() / range), rect.position.y + rect.size.y - arrow_size - bar_size);

renderer.drawStretched(sp::Rect(rect.position.x, bar_y, rect.size.x, bar_size), front.texture, front.color);
}

bool GuiScrollbar::onMouseDown(sp::io::Pointer::Button button, glm::vec2 position, sp::io::Pointer::ID id)
{
int range = (max_value - min_value);
float arrow_size = rect.size.x / 2.0f;
float move_height = (rect.size.y - arrow_size * 2);
float bar_size = move_height * value_size / range;
if (bar_size > move_height)
bar_size = move_height;
float bar_y = rect.position.y + arrow_size + move_height * getValue() / range;
float bar_y = rect.position.y + arrow_size + (move_height - bar_size) * getValue() / range;
if (position.y >= bar_y && position.y <= bar_y + bar_size)
{
drag_scrollbar = true;
Expand All @@ -56,39 +53,25 @@ void GuiScrollbar::onMouseDrag(glm::vec2 position, sp::io::Pointer::ID id)
{
if (drag_scrollbar)
{
float arrow_size = rect.size.x / 2.0f;
int range = (max_value - min_value);
float move_height = (rect.size.y - arrow_size * 2);
float bar_size = move_height * value_size / range;
if (bar_size > move_height)
bar_size = move_height;

float target_y_offset = position.y - drag_select_offset - (rect.position.y + arrow_size);
target_y_offset = std::max(target_y_offset, 0.0f);
target_y_offset = std::min(target_y_offset, move_height - bar_size);

if (bar_size < move_height)
setValue(int(target_y_offset / move_height * range + 0.5f));
setValue(int(target_y_offset / (move_height - bar_size) * range + 0.5f));
}
}

void GuiScrollbar::onMouseUp(glm::vec2 position, sp::io::Pointer::ID id)
{
if (!drag_scrollbar)
{
float arrow_size = rect.size.x / 2.0f;
int range = (max_value - min_value);
float move_height = (rect.size.y - arrow_size * 2);
float bar_size = move_height * value_size / range;
if (bar_size > move_height)
bar_size = move_height;

float target_y_offset = position.y - bar_size / 2.0f - (rect.position.y + arrow_size);
target_y_offset = std::max(target_y_offset, 0.0f);
target_y_offset = std::min(target_y_offset, move_height - bar_size);

if (bar_size < move_height)
setValue(int(target_y_offset / move_height * range + 0.5f));
setValue(int(target_y_offset / (move_height - bar_size) * range + 0.5f));
}
}

Expand Down Expand Up @@ -126,6 +109,7 @@ int GuiScrollbar::getValue() const
value = max_value - value_size;
if (value < min_value)
value = min_value;

return value;
}

Expand Down
5 changes: 5 additions & 0 deletions src/gui/gui2_scrollbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class GuiScrollbar : public GuiElement
bool drag_scrollbar;
float drag_select_offset;

int range;
float arrow_size;
float move_height;
float bar_size;

const GuiThemeStyle* back_style;
const GuiThemeStyle* front_style;
public:
Expand Down

0 comments on commit 6eb8449

Please sign in to comment.