mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
UI: Make vertical scrollbars directly draggable.
This commit is contained in:
parent
725f9ad78f
commit
69ff11fb40
2 changed files with 87 additions and 17 deletions
|
@ -1,6 +1,7 @@
|
|||
#include "Common/UI/Context.h"
|
||||
#include "Common/UI/ScrollView.h"
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Log.h"
|
||||
|
||||
namespace UI {
|
||||
|
||||
|
@ -134,7 +135,15 @@ const float friction = 0.92f;
|
|||
const float stop_threshold = 0.1f;
|
||||
|
||||
bool ScrollView::Touch(const TouchInput &input) {
|
||||
if ((input.flags & TOUCH_DOWN) && scrollTouchId_ == -1) {
|
||||
if ((input.flags & TOUCH_DOWN) && scrollTouchId_ == -1 && bounds_.Contains(input.x, input.y)) {
|
||||
if (orientation_ == ORIENT_VERTICAL) {
|
||||
Bob bob = ComputeBob();
|
||||
float internalY = input.y - bounds_.y;
|
||||
draggingBob_ = internalY >= bob.offset && internalY <= bob.offset + bob.size && input.x >= bounds_.x2() - 20.0f;
|
||||
barDragStart_ = bob.offset;
|
||||
barDragOffset_ = internalY - bob.offset;
|
||||
}
|
||||
|
||||
scrollStart_ = scrollPos_;
|
||||
inertia_ = 0.0f;
|
||||
scrollTouchId_ = input.id;
|
||||
|
@ -148,17 +157,35 @@ bool ScrollView::Touch(const TouchInput &input) {
|
|||
inertia_ = info[1];
|
||||
}
|
||||
scrollTouchId_ = -1;
|
||||
draggingBob_ = false;
|
||||
}
|
||||
|
||||
TouchInput input2;
|
||||
if (CanScroll()) {
|
||||
input2 = gesture_.Update(input, bounds_);
|
||||
float info[4];
|
||||
if (input.id == scrollTouchId_ && gesture_.GetGestureInfo(gesture, input.id, info) && !(input.flags & TOUCH_DOWN)) {
|
||||
float pos = scrollStart_ - info[0];
|
||||
scrollPos_ = pos;
|
||||
scrollTarget_ = pos;
|
||||
if (draggingBob_) {
|
||||
input2 = input;
|
||||
// Skip the gesture, do calculations directly.
|
||||
// Might switch to the gesture later.
|
||||
Bob bob = ComputeBob();
|
||||
float internalY = input.y - bounds_.y;
|
||||
|
||||
float bobPos = internalY - barDragOffset_;
|
||||
float bobDragMax = bounds_.h - bob.size;
|
||||
|
||||
float newScrollPos = Clamp(bobPos / bobDragMax, 0.0f, 1.0f) * bob.scrollMax;
|
||||
|
||||
scrollPos_ = newScrollPos;
|
||||
scrollTarget_ = newScrollPos;
|
||||
scrollToTarget_ = false;
|
||||
} else {
|
||||
input2 = gesture_.Update(input, bounds_);
|
||||
float info[4];
|
||||
if (input.id == scrollTouchId_ && gesture_.GetGestureInfo(gesture, input.id, info) && !(input.flags & TOUCH_DOWN)) {
|
||||
float pos = scrollStart_ - info[0];
|
||||
scrollPos_ = pos;
|
||||
scrollTarget_ = pos;
|
||||
scrollToTarget_ = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
input2 = input;
|
||||
|
@ -173,6 +200,22 @@ bool ScrollView::Touch(const TouchInput &input) {
|
|||
}
|
||||
}
|
||||
|
||||
ScrollView::Bob ScrollView::ComputeBob() const {
|
||||
Bob bob{};
|
||||
float childHeight = std::max(0.01f, views_[0]->GetBounds().h);
|
||||
float scrollMax = std::max(0.0f, childHeight - bounds_.h);
|
||||
float ratio = bounds_.h / childHeight;
|
||||
|
||||
if (ratio < 1.0f && scrollMax > 0.0f) {
|
||||
bob.show = true;
|
||||
bob.thickness = draggingBob_ ? 15.0f : 5.0f;
|
||||
bob.size = ratio * bounds_.h;
|
||||
bob.offset = (HardClampedScrollPos(scrollPos_) / scrollMax) * (bounds_.h - bob.size);
|
||||
bob.scrollMax = scrollMax;
|
||||
}
|
||||
return bob;
|
||||
}
|
||||
|
||||
void ScrollView::Draw(UIContext &dc) {
|
||||
if (!views_.size()) {
|
||||
ViewGroup::Draw(dc);
|
||||
|
@ -187,18 +230,16 @@ void ScrollView::Draw(UIContext &dc) {
|
|||
views_[0]->Draw(dc);
|
||||
dc.PopScissor();
|
||||
|
||||
float childHeight = views_[0]->GetBounds().h;
|
||||
float scrollMax = std::max(0.0f, childHeight - bounds_.h);
|
||||
// Vertical scroll bob. We don't support a horizontal yet.
|
||||
if (orientation_ != ORIENT_VERTICAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
float ratio = bounds_.h / std::max(0.01f, views_[0]->GetBounds().h);
|
||||
Bob bob = ComputeBob();
|
||||
|
||||
float bobWidth = 5;
|
||||
if (ratio < 1.0f && scrollMax > 0.0f) {
|
||||
float bobHeight = ratio * bounds_.h;
|
||||
float bobOffset = (ClampedScrollPos(scrollPos_) / scrollMax) * (bounds_.h - bobHeight);
|
||||
|
||||
Bounds bob(bounds_.x2() - bobWidth, bounds_.y + bobOffset, bobWidth, bobHeight);
|
||||
dc.FillRect(Drawable(0x80FFFFFF), bob);
|
||||
if (bob.show) {
|
||||
Bounds bobBounds(bounds_.x2() - bob.thickness, bounds_.y + bob.offset, bob.thickness, bob.size);
|
||||
dc.FillRect(Drawable(0x80FFFFFF), bobBounds);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,6 +372,16 @@ void ScrollView::ScrollRelative(float distance) {
|
|||
scrollToTarget_ = true;
|
||||
}
|
||||
|
||||
float ScrollView::HardClampedScrollPos(float pos) const {
|
||||
if (!views_.size() || bounds_.h == 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
float childSize = orientation_ == ORIENT_VERTICAL ? views_[0]->GetBounds().h : views_[0]->GetBounds().w;
|
||||
float containerSize = (orientation_ == ORIENT_VERTICAL ? bounds_.h : bounds_.w);
|
||||
float scrollMax = std::max(0.0f, childSize - containerSize);
|
||||
return Clamp(pos, 0.0f, scrollMax);
|
||||
}
|
||||
|
||||
float ScrollView::ClampedScrollPos(float pos) {
|
||||
if (!views_.size() || bounds_.h == 0.0f) {
|
||||
return 0.0f;
|
||||
|
@ -342,6 +393,7 @@ float ScrollView::ClampedScrollPos(float pos) {
|
|||
|
||||
Gesture gesture = orientation_ == ORIENT_VERTICAL ? GESTURE_DRAG_VERTICAL : GESTURE_DRAG_HORIZONTAL;
|
||||
|
||||
// TODO: Not all of this is properly orientation independent.
|
||||
if (scrollTouchId_ >= 0 && gesture_.IsGestureActive(gesture, scrollTouchId_) && bounds_.h > 0.0f) {
|
||||
float maxPull = bounds_.h * 0.1f;
|
||||
if (pos < 0.0f) {
|
||||
|
|
|
@ -47,8 +47,22 @@ public:
|
|||
NeighborResult FindScrollNeighbor(View *view, const Point &target, FocusDirection direction, NeighborResult best) override;
|
||||
|
||||
private:
|
||||
float HardClampedScrollPos(float pos) const;
|
||||
|
||||
// TODO: Don't adjust pull_ within this!
|
||||
float ClampedScrollPos(float pos);
|
||||
|
||||
// The "bob" is the draggable thingy on a scroll bar. Don't know a better name for it.
|
||||
struct Bob {
|
||||
bool show;
|
||||
float thickness;
|
||||
float size;
|
||||
float offset;
|
||||
float scrollMax;
|
||||
};
|
||||
|
||||
Bob ComputeBob() const;
|
||||
|
||||
GestureDetector gesture_;
|
||||
Orientation orientation_;
|
||||
float scrollPos_ = 0.0f;
|
||||
|
@ -62,6 +76,10 @@ private:
|
|||
float lastViewSize_ = 0.0f;
|
||||
float *rememberPos_ = nullptr;
|
||||
bool alignOpposite_ = false;
|
||||
bool draggingBob_ = false;
|
||||
|
||||
float barDragStart_ = 0.0f;
|
||||
float barDragOffset_ = 0.0f;
|
||||
|
||||
static float lastScrollPosX;
|
||||
static float lastScrollPosY;
|
||||
|
|
Loading…
Add table
Reference in a new issue