Allow animated scroll-to in BoxContent.

This commit is contained in:
John Preston 2024-04-23 19:11:31 +04:00
parent ae5a61f7ae
commit 27b7534734
4 changed files with 46 additions and 10 deletions

View file

@ -263,8 +263,21 @@ RectParts BoxContent::customCornersFilling() {
}
void BoxContent::scrollToY(int top, int bottom) {
scrollTo({ top, bottom });
}
void BoxContent::scrollTo(ScrollToRequest request, anim::type animated) {
if (_scroll) {
_scroll->scrollToY(top, bottom);
const auto v = _scroll->computeScrollTo(request.ymin, request.ymax);
const auto now = _scroll->scrollTop();
if (animated == anim::type::instant || v == now) {
_scrollAnimation.stop();
_scroll->scrollToY(v);
} else {
_scrollAnimation.start([=] {
_scroll->scrollToY(_scrollAnimation.value(v));
}, now, v, st::slideWrapDuration, anim::sineInOut);
}
}
}

View file

@ -13,6 +13,7 @@
#include "ui/widgets/labels.h"
#include "ui/layers/layer_widget.h"
#include "ui/layers/show.h"
#include "ui/effects/animations.h"
#include "ui/effects/animation_value.h"
#include "ui/text/text_entity.h"
#include "ui/rp_widget.h"
@ -59,6 +60,7 @@ class ScrollArea;
class FlatLabel;
class FadeShadow;
class BoxContent;
struct ScrollToRequest;
class BoxContentDelegate {
public:
@ -213,6 +215,9 @@ public:
void scrollByDraggingDelta(int delta);
void scrollToY(int top, int bottom = -1);
void scrollTo(
ScrollToRequest request,
anim::type animated = anim::type::instant);
void sendScrollViewportEvent(not_null<QEvent*> event);
[[nodiscard]] rpl::producer<> scrolls() const;
[[nodiscard]] int scrollTop() const;
@ -309,6 +314,7 @@ private:
object_ptr<FadeShadow> _bottomShadow = { nullptr };
Ui::DraggingScrollManager _draggingScroll;
Ui::Animations::Simple _scrollAnimation;
rpl::event_stream<> _boxClosingStream;

View file

@ -706,32 +706,48 @@ void ScrollArea::scrollToWidget(not_null<QWidget*> widget) {
}
}
void ScrollArea::scrollToY(int toTop, int toBottom) {
int ScrollArea::computeScrollTo(int toTop, int toBottom) {
if (const auto inner = widget()) {
SendPendingMoveResizeEvents(inner);
}
SendPendingMoveResizeEvents(this);
int toMin = 0, toMax = scrollTopMax();
const auto toMin = 0;
const auto toMax = scrollTopMax();
if (toTop < toMin) {
toTop = toMin;
} else if (toTop > toMax) {
toTop = toMax;
}
bool exact = (toBottom < 0);
const auto exact = (toBottom < 0);
int curTop = scrollTop(), curHeight = height(), curBottom = curTop + curHeight, scToTop = toTop;
const auto curTop = scrollTop();
const auto curHeight = height();
const auto curBottom = curTop + curHeight;
auto scToTop = toTop;
if (!exact && toTop >= curTop) {
if (toBottom < toTop) toBottom = toTop;
if (toBottom <= curBottom) return;
if (toBottom < toTop) {
toBottom = toTop;
}
if (toBottom <= curBottom) {
return curTop;
}
scToTop = toBottom - curHeight;
if (scToTop > toTop) scToTop = toTop;
if (scToTop == curTop) return;
if (scToTop > toTop) {
scToTop = toTop;
}
if (scToTop == curTop) {
return curTop;
}
} else {
scToTop = toTop;
}
verticalScrollBar()->setValue(scToTop);
return scToTop;
}
void ScrollArea::scrollToY(int toTop, int toBottom) {
verticalScrollBar()->setValue(computeScrollTo(toTop, toBottom));
}
void ScrollArea::doSetOwnedWidget(object_ptr<QWidget> w) {

View file

@ -166,6 +166,7 @@ public:
void scrollTo(ScrollToRequest request);
void scrollToWidget(not_null<QWidget*> widget);
[[nodiscard]] int computeScrollTo(int toTop, int toBottom);
void scrollToY(int toTop, int toBottom = -1);
void disableScroll(bool dis);