Add a scrollbar to the list view
This commit is contained in:
parent
e27cbe5bd9
commit
9745942130
7 changed files with 178 additions and 94 deletions
|
|
@ -25,27 +25,27 @@ bool Scrollbar::IsHorizontal() const
|
|||
return !vertical;
|
||||
}
|
||||
|
||||
int Scrollbar::GetMin() const
|
||||
double Scrollbar::GetMin() const
|
||||
{
|
||||
return scroll_min;
|
||||
}
|
||||
|
||||
int Scrollbar::GetMax() const
|
||||
double Scrollbar::GetMax() const
|
||||
{
|
||||
return scroll_max;
|
||||
}
|
||||
|
||||
int Scrollbar::GetLineStep() const
|
||||
double Scrollbar::GetLineStep() const
|
||||
{
|
||||
return line_step;
|
||||
}
|
||||
|
||||
int Scrollbar::GetPageStep() const
|
||||
double Scrollbar::GetPageStep() const
|
||||
{
|
||||
return page_step;
|
||||
}
|
||||
|
||||
int Scrollbar::GetPosition() const
|
||||
double Scrollbar::GetPosition() const
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
|
@ -64,61 +64,61 @@ void Scrollbar::SetHorizontal()
|
|||
Update();
|
||||
}
|
||||
|
||||
void Scrollbar::SetMin(int new_scroll_min)
|
||||
void Scrollbar::SetMin(double new_scroll_min)
|
||||
{
|
||||
SetRanges(new_scroll_min, scroll_max, line_step, page_step);
|
||||
}
|
||||
|
||||
void Scrollbar::SetMax(int new_scroll_max)
|
||||
void Scrollbar::SetMax(double new_scroll_max)
|
||||
{
|
||||
SetRanges(scroll_min, new_scroll_max, line_step, page_step);
|
||||
}
|
||||
|
||||
void Scrollbar::SetLineStep(int step)
|
||||
void Scrollbar::SetLineStep(double step)
|
||||
{
|
||||
SetRanges(scroll_min, scroll_max, step, page_step);
|
||||
}
|
||||
|
||||
void Scrollbar::SetPageStep(int step)
|
||||
void Scrollbar::SetPageStep(double step)
|
||||
{
|
||||
SetRanges(scroll_min, scroll_max, line_step, step);
|
||||
}
|
||||
|
||||
void Scrollbar::SetRanges(int scroll_min, int scroll_max, int line_step, int page_step)
|
||||
void Scrollbar::SetRanges(double new_scroll_min, double new_scroll_max, double new_line_step, double new_page_step)
|
||||
{
|
||||
if (scroll_min >= scroll_max || line_step <= 0 || page_step <= 0)
|
||||
if (new_scroll_min >= new_scroll_max || new_line_step <= 0.0 || new_page_step <= 0.0)
|
||||
throw std::runtime_error("Scrollbar ranges out of bounds!");
|
||||
scroll_min = scroll_min;
|
||||
scroll_max = scroll_max;
|
||||
line_step = line_step;
|
||||
page_step = page_step;
|
||||
scroll_min = new_scroll_min;
|
||||
scroll_max = new_scroll_max;
|
||||
line_step = new_line_step;
|
||||
page_step = new_page_step;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (position < scroll_min)
|
||||
position = scroll_min;
|
||||
if (UpdatePartPositions())
|
||||
Update();
|
||||
}
|
||||
|
||||
void Scrollbar::SetRanges(int view_size, int total_size)
|
||||
void Scrollbar::SetRanges(double view_size, double total_size)
|
||||
{
|
||||
if (view_size <= 0 || total_size <= 0)
|
||||
if (view_size <= 0.0 || total_size <= 0.0)
|
||||
{
|
||||
SetRanges(0, 1, 1, 1);
|
||||
SetRanges(0.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int scroll_max = std::max(1, total_size - view_size + 1);
|
||||
int page_step = std::max(1, view_size);
|
||||
SetRanges(0, scroll_max, 1, page_step);
|
||||
double scroll_max = std::max(1.0, total_size - view_size + 1.0);
|
||||
double page_step = std::max(1.0, view_size);
|
||||
SetRanges(0.0, scroll_max, 10, page_step);
|
||||
}
|
||||
}
|
||||
|
||||
void Scrollbar::SetPosition(int pos)
|
||||
void Scrollbar::SetPosition(double pos)
|
||||
{
|
||||
position = pos;
|
||||
if (pos >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (pos < scroll_min)
|
||||
position = scroll_min;
|
||||
|
||||
|
|
@ -130,24 +130,24 @@ void Scrollbar::OnMouseMove(const Point& pos)
|
|||
{
|
||||
if (mouse_down_mode == mouse_down_thumb_drag)
|
||||
{
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
|
||||
if (pos.x < -100 || pos.x > GetWidth() + 100 || pos.y < -100 || pos.y > GetHeight() + 100)
|
||||
if (pos.x < -100.0 || pos.x > GetWidth() + 100.0 || pos.y < -100.0 || pos.y > GetHeight() + 100.0)
|
||||
{
|
||||
position = thumb_start_position;
|
||||
}
|
||||
else
|
||||
{
|
||||
int delta = (int)(vertical ? (pos.y - mouse_drag_start_pos.y) : (pos.x - mouse_drag_start_pos.x));
|
||||
int position_pixels = thumb_start_pixel_position + delta;
|
||||
double delta = vertical ? (pos.y - mouse_drag_start_pos.y) : (pos.x - mouse_drag_start_pos.x);
|
||||
double position_pixels = thumb_start_pixel_position + delta;
|
||||
|
||||
int track_height = 0;
|
||||
double track_height = 0;
|
||||
if (vertical)
|
||||
track_height = (int)(rect_track_decrement.height + rect_track_increment.height);
|
||||
track_height = rect_track_decrement.height + rect_track_increment.height;
|
||||
else
|
||||
track_height = (int)(rect_track_decrement.width + rect_track_increment.width);
|
||||
track_height = rect_track_decrement.width + rect_track_increment.width;
|
||||
|
||||
if (track_height != 0)
|
||||
if (track_height != 0.0)
|
||||
position = scroll_min + position_pixels * (scroll_max - scroll_min) / track_height;
|
||||
else
|
||||
position = 0;
|
||||
|
|
@ -178,12 +178,12 @@ void Scrollbar::OnMouseDown(const Point& pos, int key)
|
|||
mouse_down_mode = mouse_down_button_decr;
|
||||
FuncScrollOnMouseDown = &FuncScrollLineDecrement;
|
||||
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
|
||||
position -= line_step;
|
||||
last_step_size = -line_step;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (position < scroll_min)
|
||||
position = scroll_min;
|
||||
|
||||
|
|
@ -195,12 +195,12 @@ void Scrollbar::OnMouseDown(const Point& pos, int key)
|
|||
mouse_down_mode = mouse_down_button_incr;
|
||||
FuncScrollOnMouseDown = &FuncScrollLineIncrement;
|
||||
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
|
||||
position += line_step;
|
||||
last_step_size = line_step;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (position < scroll_min)
|
||||
position = scroll_min;
|
||||
|
||||
|
|
@ -211,19 +211,19 @@ void Scrollbar::OnMouseDown(const Point& pos, int key)
|
|||
{
|
||||
mouse_down_mode = mouse_down_thumb_drag;
|
||||
thumb_start_position = position;
|
||||
thumb_start_pixel_position = (int)(vertical ? (rect_thumb.y - rect_track_decrement.y) : (rect_thumb.x - rect_track_decrement.x));
|
||||
thumb_start_pixel_position = vertical ? (rect_thumb.y - rect_track_decrement.y) : (rect_thumb.x - rect_track_decrement.x);
|
||||
}
|
||||
else if (rect_track_decrement.contains(pos))
|
||||
{
|
||||
mouse_down_mode = mouse_down_track_decr;
|
||||
FuncScrollOnMouseDown = &FuncScrollPageDecrement;
|
||||
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
|
||||
position -= page_step;
|
||||
last_step_size = -page_step;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (position < scroll_min)
|
||||
position = scroll_min;
|
||||
|
||||
|
|
@ -235,12 +235,12 @@ void Scrollbar::OnMouseDown(const Point& pos, int key)
|
|||
mouse_down_mode = mouse_down_track_incr;
|
||||
FuncScrollOnMouseDown = &FuncScrollPageIncrement;
|
||||
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
|
||||
position += page_step;
|
||||
last_step_size = page_step;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
position = scroll_max - 1.0;
|
||||
if (position < scroll_min)
|
||||
position = scroll_min;
|
||||
|
||||
|
|
@ -291,20 +291,26 @@ void Scrollbar::OnPaint(Canvas* canvas)
|
|||
part_track_increment.render_box(canvas, rect_track_increment);
|
||||
part_button_increment.render_box(canvas, rect_button_increment);
|
||||
*/
|
||||
|
||||
canvas->fillRect(Rect::shrink(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight()), 4.0, 0.0, 4.0, 0.0), Colorf::fromRgba8(33, 33, 33));
|
||||
canvas->fillRect(Rect::shrink(rect_thumb, 4.0, 0.0, 4.0, 0.0), Colorf::fromRgba8(58, 58, 58));
|
||||
}
|
||||
|
||||
// Calculates positions of all parts. Returns true if thumb position was changed compared to previously, false otherwise.
|
||||
bool Scrollbar::UpdatePartPositions()
|
||||
{
|
||||
int total_height = (int)(vertical ? GetHeight() : GetWidth());
|
||||
int track_height = std::max(0, total_height - decr_height - incr_height);
|
||||
int thumb_height = CalculateThumbSize(track_height);
|
||||
double decr_height = showbuttons ? 16.0 : 0.0;
|
||||
double incr_height = showbuttons ? 16.0 : 0.0;
|
||||
|
||||
int thumb_offset = decr_height + CalculateThumbPosition(thumb_height, track_height);
|
||||
double total_height = vertical ? GetHeight() : GetWidth();
|
||||
double track_height = std::max(0.0, total_height - decr_height - incr_height);
|
||||
double thumb_height = CalculateThumbSize(track_height);
|
||||
|
||||
double thumb_offset = decr_height + CalculateThumbPosition(thumb_height, track_height);
|
||||
|
||||
Rect previous_rect_thumb = rect_thumb;
|
||||
|
||||
rect_button_decrement = CreateRect(0, decr_height);
|
||||
rect_button_decrement = CreateRect(0.0, decr_height);
|
||||
rect_track_decrement = CreateRect(decr_height, thumb_offset);
|
||||
rect_thumb = CreateRect(thumb_offset, thumb_offset + thumb_height);
|
||||
rect_track_increment = CreateRect(thumb_offset + thumb_height, decr_height + track_height);
|
||||
|
|
@ -313,12 +319,12 @@ bool Scrollbar::UpdatePartPositions()
|
|||
return (previous_rect_thumb != rect_thumb);
|
||||
}
|
||||
|
||||
int Scrollbar::CalculateThumbSize(int track_size)
|
||||
double Scrollbar::CalculateThumbSize(double track_size)
|
||||
{
|
||||
int minimum_thumb_size = 20;
|
||||
int range = scroll_max - scroll_min;
|
||||
int length = range + page_step - 1;
|
||||
int thumb_size = page_step * track_size / length;
|
||||
double minimum_thumb_size = 20.0;
|
||||
double range = scroll_max - scroll_min;
|
||||
double length = range + page_step - 1;
|
||||
double thumb_size = page_step * track_size / length;
|
||||
if (thumb_size < minimum_thumb_size)
|
||||
thumb_size = minimum_thumb_size;
|
||||
if (thumb_size > track_size)
|
||||
|
|
@ -326,13 +332,13 @@ int Scrollbar::CalculateThumbSize(int track_size)
|
|||
return thumb_size;
|
||||
}
|
||||
|
||||
int Scrollbar::CalculateThumbPosition(int thumb_size, int track_size)
|
||||
double Scrollbar::CalculateThumbPosition(double thumb_size, double track_size)
|
||||
{
|
||||
int relative_pos = position - scroll_min;
|
||||
int range = scroll_max - scroll_min - 1;
|
||||
double relative_pos = position - scroll_min;
|
||||
double range = scroll_max - scroll_min - 1;
|
||||
if (range != 0)
|
||||
{
|
||||
int available_area = std::max(0, track_size - thumb_size);
|
||||
double available_area = std::max(0.0, track_size - thumb_size);
|
||||
return relative_pos * available_area / range;
|
||||
}
|
||||
else
|
||||
|
|
@ -341,7 +347,7 @@ int Scrollbar::CalculateThumbPosition(int thumb_size, int track_size)
|
|||
}
|
||||
}
|
||||
|
||||
Rect Scrollbar::CreateRect(int start, int end)
|
||||
Rect Scrollbar::CreateRect(double start, double end)
|
||||
{
|
||||
if (vertical)
|
||||
return Rect(0.0, start, GetWidth(), end - start);
|
||||
|
|
@ -356,7 +362,7 @@ void Scrollbar::OnTimerExpired()
|
|||
|
||||
mouse_down_timer->Start(100, false);
|
||||
|
||||
int last_position = position;
|
||||
double last_position = position;
|
||||
position += last_step_size;
|
||||
if (position >= scroll_max)
|
||||
position = scroll_max - 1;
|
||||
|
|
@ -395,6 +401,6 @@ void Scrollbar::InvokeScrollEvent(std::function<void()>* event_ptr)
|
|||
if (FuncScroll)
|
||||
FuncScroll();
|
||||
|
||||
if (event_ptr)
|
||||
if (event_ptr && *event_ptr)
|
||||
(*event_ptr)();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue