BScrollView: Automatically update the scrollbar proportions in layout mode.

Since we know what size the target view is / wants to be, we can automatically
set the range, steps, and proportion trivially. In non-layout mode, we retain
the old behavior. Applications or views that need custom scrolling behavior almost
certainly will be using BScrollBars directly and not this, so this should not be
"wasted computation" in pretty much any case.

Greatly improves the appearance and UX of the default case of a layouted
view inside a BScrollView.

Change-Id: Ia6ff6ee14df96799c579e15d274fd4c849675577
Reviewed-on: https://review.haiku-os.org/c/892
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Augustin Cavalier 2019-01-22 13:36:03 -05:00 committed by waddlesplash
parent 2502d45aca
commit 5b0e5c0ac6
2 changed files with 45 additions and 12 deletions

View File

@ -1,13 +1,13 @@
/*
* Copyright 2014 Haiku, Inc. All rights reserved.
* Copyright 2014-2019, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* John Scipione, jscipione@gmail.com
*
* Corresponds to:
* headers/os/interface/ScrollView.h hrev47312
* src/kits/interface/ScrollView.cpp hrev47312
* headers/os/interface/ScrollView.h hrev52792
* src/kits/interface/ScrollView.cpp hrev52792
*/
@ -216,7 +216,8 @@
\fn void BScrollView::FrameResized(float newWidth, float newHeight)
\brief Hook method called when the scroll view is resized.
\copydetails BView::FrameResized()
If the scroll view is part of a layout, the default implementation will
re-proportion the attached scrollbars relative to the new size.
*/

View File

@ -42,7 +42,7 @@ BScrollView::BScrollView(const char* name, BView* target, uint32 resizingMode,
BScrollView::BScrollView(const char* name, BView* target, uint32 flags,
bool horizontal, bool vertical, border_style border)
:
BView(name, _ModifyFlags(flags, border)),
BView(name, _ModifyFlags(flags | B_SUPPORTS_LAYOUT, border)),
fTarget(target),
fBorder(border)
{
@ -271,10 +271,37 @@ BScrollView::FrameResized(float newWidth, float newHeight)
{
BView::FrameResized(newWidth, newHeight);
const BRect bounds = Bounds();
if ((Flags() & B_SUPPORTS_LAYOUT) != 0) {
BSize size = fTarget != NULL ? fTarget->PreferredSize() : BSize();
if (fHorizontalScrollBar != NULL) {
float delta = size.Width() - bounds.Width(),
proportion = bounds.Width() / size.Width();
if (delta < 0)
delta = 0;
fHorizontalScrollBar->SetRange(0, delta);
fHorizontalScrollBar->SetSteps(be_plain_font->Size() * 1.33,
bounds.Width());
fHorizontalScrollBar->SetProportion(proportion);
}
if (fVerticalScrollBar != NULL) {
float delta = size.Height() - bounds.Height(),
proportion = bounds.Height() / size.Height();
if (delta < 0)
delta = 0;
fVerticalScrollBar->SetRange(0, delta);
fVerticalScrollBar->SetSteps(be_plain_font->Size() * 1.33,
bounds.Height());
fVerticalScrollBar->SetProportion(proportion);
}
}
if (fBorder == B_NO_BORDER)
return;
BRect bounds = Bounds();
float border = _BorderSize() - 1;
if (fHorizontalScrollBar != NULL && fVerticalScrollBar != NULL) {
@ -443,7 +470,7 @@ BScrollView::SetBorder(border_style border)
if (fBorder == border)
return;
if (Flags() & B_SUPPORTS_LAYOUT) {
if ((Flags() & B_SUPPORTS_LAYOUT) != 0) {
fBorder = border;
SetFlags(_ModifyFlags(Flags(), border));
@ -928,12 +955,17 @@ BScrollView::_BorderSize(border_style border)
/*static*/ int32
BScrollView::_ModifyFlags(int32 flags, border_style border)
{
// We either need B_FULL_UPDATE_ON_RESIZE or
// B_FRAME_EVENTS if we have to draw a border
if (border != B_NO_BORDER)
return flags | B_WILL_DRAW | (flags & B_FULL_UPDATE_ON_RESIZE ? 0 : B_FRAME_EVENTS);
if ((flags & B_SUPPORTS_LAYOUT) != 0)
flags |= B_FRAME_EVENTS;
return flags & ~(B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE);
// We either need B_FULL_UPDATE_ON_RESIZE or B_FRAME_EVENTS if we have
// to draw a border.
if (border != B_NO_BORDER) {
flags |= B_WILL_DRAW | ((flags & B_FULL_UPDATE_ON_RESIZE) != 0 ?
0 : B_FRAME_EVENTS);
}
return flags;
}