mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Nice expand / collapse animations.
This commit is contained in:
parent
aff094f278
commit
7f583f86c0
3 changed files with 125 additions and 30 deletions
|
@ -1137,7 +1137,16 @@ void Widget::scrollToDefault(bool verytop) {
|
||||||
startScrollUpButtonAnimation(false);
|
startScrollUpButtonAnimation(false);
|
||||||
|
|
||||||
const auto scroll = [=] {
|
const auto scroll = [=] {
|
||||||
_scroll->scrollToY(qRound(_scrollToAnimation.value(scrollTo)));
|
const auto animated = qRound(_scrollToAnimation.value(scrollTo));
|
||||||
|
const auto animatedDelta = animated - scrollTo;
|
||||||
|
const auto realDelta = _scroll->scrollTop() - scrollTo;
|
||||||
|
if (realDelta * animatedDelta < 0) {
|
||||||
|
// We scrolled manually to the other side of target 'scrollTo'.
|
||||||
|
_scrollToAnimation.stop();
|
||||||
|
} else if (std::abs(realDelta) > std::abs(animatedDelta)) {
|
||||||
|
// We scroll by animation only if it gets us closer to target.
|
||||||
|
_scroll->scrollToY(animated);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_scrollToAnimation.start(
|
_scrollToAnimation.start(
|
||||||
|
@ -2019,7 +2028,6 @@ void Widget::dropEvent(QDropEvent *e) {
|
||||||
|
|
||||||
void Widget::listScrollUpdated() {
|
void Widget::listScrollUpdated() {
|
||||||
const auto scrollTop = _scroll->scrollTop();
|
const auto scrollTop = _scroll->scrollTop();
|
||||||
PROFILE_LOG(("SCROLLED: %1").arg(scrollTop));
|
|
||||||
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
_inner->setVisibleTopBottom(scrollTop, scrollTop + _scroll->height());
|
||||||
updateScrollUpVisibility();
|
updateScrollUpVisibility();
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,12 @@ namespace Dialogs::Stories {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kSmallThumbsShown = 3;
|
constexpr auto kSmallThumbsShown = 3;
|
||||||
constexpr auto kSummaryExpandLeft = 1.5;
|
constexpr auto kSummaryExpandLeft = 1;
|
||||||
constexpr auto kPreloadPages = 2;
|
constexpr auto kPreloadPages = 2;
|
||||||
|
constexpr auto kExpandAfterRatio = 0.85;
|
||||||
|
constexpr auto kCollapseAfterRatio = 0.72;
|
||||||
|
constexpr auto kFrictionRatio = 0.15;
|
||||||
|
constexpr auto kSnapExpandedTimeout = crl::time(200);
|
||||||
|
|
||||||
[[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) {
|
[[nodiscard]] int AvailableNameWidth(const style::DialogsStoriesList &st) {
|
||||||
const auto &full = st.full;
|
const auto &full = st.full;
|
||||||
|
@ -33,6 +37,7 @@ constexpr auto kPreloadPages = 2;
|
||||||
struct List::Layout {
|
struct List::Layout {
|
||||||
int itemsCount = 0;
|
int itemsCount = 0;
|
||||||
int shownHeight = 0;
|
int shownHeight = 0;
|
||||||
|
float64 expandedRatio = 0.;
|
||||||
float64 ratio = 0.;
|
float64 ratio = 0.;
|
||||||
float64 thumbnailLeft = 0.;
|
float64 thumbnailLeft = 0.;
|
||||||
float64 photoLeft = 0.;
|
float64 photoLeft = 0.;
|
||||||
|
@ -56,7 +61,8 @@ List::List(
|
||||||
Fn<int()> shownHeight)
|
Fn<int()> shownHeight)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _shownHeight(shownHeight) {
|
, _shownHeight(shownHeight)
|
||||||
|
, _snapExpandedTimer([=] { requestExpanded(_expanded); }) {
|
||||||
setCursor(style::cur_default);
|
setCursor(style::cur_default);
|
||||||
|
|
||||||
std::move(content) | rpl::start_with_next([=](Content &&content) {
|
std::move(content) | rpl::start_with_next([=](Content &&content) {
|
||||||
|
@ -251,6 +257,20 @@ rpl::producer<> List::loadMoreRequests() const {
|
||||||
return _loadMoreRequests.events();
|
return _loadMoreRequests.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void List::requestExpanded(bool expanded) {
|
||||||
|
_snapExpandedTimer.cancel();
|
||||||
|
if (_expanded != expanded) {
|
||||||
|
_expanded = expanded;
|
||||||
|
_expandedAnimation.start(
|
||||||
|
[=] { update(); },
|
||||||
|
_expanded ? 0. : 1.,
|
||||||
|
_expanded ? 1. : 0.,
|
||||||
|
st::slideWrapDuration,
|
||||||
|
anim::sineInOut);
|
||||||
|
}
|
||||||
|
_toggleExpandedRequests.fire_copy(_expanded);
|
||||||
|
}
|
||||||
|
|
||||||
void List::enterEventHook(QEnterEvent *e) {
|
void List::enterEventHook(QEnterEvent *e) {
|
||||||
_entered.fire({});
|
_entered.fire({});
|
||||||
}
|
}
|
||||||
|
@ -259,12 +279,46 @@ void List::resizeEvent(QResizeEvent *e) {
|
||||||
updateScrollMax();
|
updateScrollMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
List::Layout List::computeLayout() const {
|
void List::updateExpanding(int minHeight, int shownHeight, int fullHeight) {
|
||||||
|
Expects(shownHeight == minHeight || fullHeight > minHeight);
|
||||||
|
|
||||||
|
const auto ratio = (shownHeight == minHeight)
|
||||||
|
? 0.
|
||||||
|
: (float64(shownHeight - minHeight) / (fullHeight - minHeight));
|
||||||
|
if (_lastRatio == ratio) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto expanding = (ratio > _lastRatio);
|
||||||
|
_lastRatio = ratio;
|
||||||
|
const auto change = _expanded
|
||||||
|
? (!expanding && ratio < kCollapseAfterRatio)
|
||||||
|
: (expanding && ratio > kExpandAfterRatio);
|
||||||
|
if (change) {
|
||||||
|
requestExpanded(!_expanded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List::Layout List::computeLayout() {
|
||||||
const auto &st = _st.small;
|
const auto &st = _st.small;
|
||||||
const auto &full = _st.full;
|
const auto &full = _st.full;
|
||||||
const auto shownHeight = std::max(_shownHeight(), st.height);
|
const auto shownHeight = std::max(_shownHeight(), st.height);
|
||||||
const auto ratio = float64(shownHeight - st.height)
|
if (_lastHeight != shownHeight) {
|
||||||
|
_lastHeight = shownHeight;
|
||||||
|
if (_lastHeight == st.height || _lastHeight == full.height) {
|
||||||
|
_snapExpandedTimer.cancel();
|
||||||
|
} else {
|
||||||
|
_snapExpandedTimer.callOnce(kSnapExpandedTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateExpanding(st.height, shownHeight, full.height);
|
||||||
|
|
||||||
|
const auto expanded = _expandedAnimation.value(_expanded ? 1. : 0.);
|
||||||
|
const auto expandedRatio = float64(shownHeight - st.height)
|
||||||
/ (full.height - st.height);
|
/ (full.height - st.height);
|
||||||
|
const auto collapsedRatio = expandedRatio * kFrictionRatio;
|
||||||
|
const auto ratio = expandedRatio * expanded
|
||||||
|
+ collapsedRatio * (1. - expanded);
|
||||||
|
|
||||||
const auto lerp = [&](float64 a, float64 b) {
|
const auto lerp = [&](float64 a, float64 b) {
|
||||||
return a + (b - a) * ratio;
|
return a + (b - a) * ratio;
|
||||||
};
|
};
|
||||||
|
@ -304,6 +358,7 @@ List::Layout List::computeLayout() const {
|
||||||
return Layout{
|
return Layout{
|
||||||
.itemsCount = itemsCount,
|
.itemsCount = itemsCount,
|
||||||
.shownHeight = shownHeight,
|
.shownHeight = shownHeight,
|
||||||
|
.expandedRatio = expandedRatio,
|
||||||
.ratio = ratio,
|
.ratio = ratio,
|
||||||
.thumbnailLeft = thumbnailLeft,
|
.thumbnailLeft = thumbnailLeft,
|
||||||
.photoLeft = photoLeft,
|
.photoLeft = photoLeft,
|
||||||
|
@ -326,14 +381,24 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto &full = _st.full;
|
const auto &full = _st.full;
|
||||||
const auto layout = computeLayout();
|
const auto layout = computeLayout();
|
||||||
const auto ratio = layout.ratio;
|
const auto ratio = layout.ratio;
|
||||||
|
const auto expandRatio = (ratio >= kCollapseAfterRatio)
|
||||||
|
? 1.
|
||||||
|
: (ratio <= kExpandAfterRatio * kFrictionRatio)
|
||||||
|
? 0.
|
||||||
|
: ((ratio - kExpandAfterRatio * kFrictionRatio)
|
||||||
|
/ (kCollapseAfterRatio - kExpandAfterRatio * kFrictionRatio));
|
||||||
const auto lerp = [&](float64 a, float64 b) {
|
const auto lerp = [&](float64 a, float64 b) {
|
||||||
return a + (b - a) * ratio;
|
return a + (b - a) * ratio;
|
||||||
};
|
};
|
||||||
|
const auto elerp = [&](float64 a, float64 b) {
|
||||||
|
return a + (b - a) * expandRatio;
|
||||||
|
};
|
||||||
auto &rendering = _data.empty() ? _hidingData : _data;
|
auto &rendering = _data.empty() ? _hidingData : _data;
|
||||||
const auto line = lerp(st.lineTwice, full.lineTwice) / 2.;
|
const auto line = elerp(st.lineTwice, full.lineTwice) / 2.;
|
||||||
const auto lineRead = lerp(st.lineReadTwice, full.lineReadTwice) / 2.;
|
const auto lineRead = elerp(st.lineReadTwice, full.lineReadTwice) / 2.;
|
||||||
const auto photoTopSmall = (st.height - st.photo) / 2.;
|
const auto photoTopSmall = (st.height - st.photo) / 2.;
|
||||||
const auto photoTop = lerp(photoTopSmall, full.photoTop);
|
const auto photoTop = photoTopSmall
|
||||||
|
+ (full.photoTop - photoTopSmall) * layout.expandedRatio;
|
||||||
const auto photo = lerp(st.photo, full.photo);
|
const auto photo = lerp(st.photo, full.photo);
|
||||||
const auto summaryTop = st.nameTop
|
const auto summaryTop = st.nameTop
|
||||||
- (st.photoTop + (st.photo / 2.))
|
- (st.photoTop + (st.photo / 2.))
|
||||||
|
@ -343,15 +408,15 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto nameWidth = nameScale * AvailableNameWidth(_st);
|
const auto nameWidth = nameScale * AvailableNameWidth(_st);
|
||||||
const auto nameHeight = nameScale * full.nameStyle.font->height;
|
const auto nameHeight = nameScale * full.nameStyle.font->height;
|
||||||
const auto nameLeft = layout.photoLeft + (photo - nameWidth) / 2.;
|
const auto nameLeft = layout.photoLeft + (photo - nameWidth) / 2.;
|
||||||
const auto readUserpicOpacity = lerp(_st.readOpacity, 1.);
|
const auto readUserpicOpacity = elerp(_st.readOpacity, 1.);
|
||||||
const auto readUserpicAppearingOpacity = lerp(_st.readOpacity, 0.);
|
const auto readUserpicAppearingOpacity = elerp(_st.readOpacity, 0.);
|
||||||
|
|
||||||
auto p = QPainter(this);
|
auto p = QPainter(this);
|
||||||
p.fillRect(e->rect(), _bgOverride.value_or(_st.bg));
|
p.fillRect(e->rect(), _bgOverride.value_or(_st.bg));
|
||||||
p.translate(0, height() - layout.shownHeight);
|
p.translate(0, height() - layout.shownHeight);
|
||||||
|
|
||||||
const auto drawSmall = (ratio < 1.);
|
const auto drawSmall = (expandRatio < 1.);
|
||||||
const auto drawFull = (ratio > 0.);
|
const auto drawFull = (expandRatio > 0.);
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
|
||||||
const auto count = std::max(
|
const auto count = std::max(
|
||||||
|
@ -364,6 +429,7 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
Item *itemSmall = nullptr;
|
Item *itemSmall = nullptr;
|
||||||
int indexFull = 0;
|
int indexFull = 0;
|
||||||
Item *itemFull = nullptr;
|
Item *itemFull = nullptr;
|
||||||
|
float64 photoTop = 0.;
|
||||||
|
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return itemSmall || itemFull;
|
return itemSmall || itemFull;
|
||||||
|
@ -372,6 +438,11 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto lookup = [&](int index) {
|
const auto lookup = [&](int index) {
|
||||||
const auto indexSmall = layout.startIndexSmall + index;
|
const auto indexSmall = layout.startIndexSmall + index;
|
||||||
const auto indexFull = layout.startIndexFull + index;
|
const auto indexFull = layout.startIndexFull + index;
|
||||||
|
const auto ySmall = photoTopSmall
|
||||||
|
+ ((indexSmall - layout.smallSkip + 1)
|
||||||
|
* (photoTop - photoTopSmall) / 3.);
|
||||||
|
const auto y = elerp(ySmall, photoTop);
|
||||||
|
|
||||||
const auto small = (drawSmall
|
const auto small = (drawSmall
|
||||||
&& indexSmall < layout.endIndexSmall
|
&& indexSmall < layout.endIndexSmall
|
||||||
&& indexSmall >= layout.smallSkip)
|
&& indexSmall >= layout.smallSkip)
|
||||||
|
@ -381,7 +452,7 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
? &rendering.items[indexFull]
|
? &rendering.items[indexFull]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
const auto x = layout.left + layout.single * index;
|
const auto x = layout.left + layout.single * index;
|
||||||
return Single{ x, indexSmall, small, indexFull, full };
|
return Single{ x, indexSmall, small, indexFull, full, y };
|
||||||
};
|
};
|
||||||
const auto hasUnread = [&](const Single &single) {
|
const auto hasUnread = [&](const Single &single) {
|
||||||
return (single.itemSmall && single.itemSmall->element.unread)
|
return (single.itemSmall && single.itemSmall->element.unread)
|
||||||
|
@ -427,18 +498,23 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
enumerate([&](Single single) {
|
enumerate([&](Single single) {
|
||||||
// Name.
|
// Name.
|
||||||
if (const auto full = single.itemFull) {
|
if (const auto full = single.itemFull) {
|
||||||
p.setOpacity(ratio);
|
|
||||||
validateName(full);
|
validateName(full);
|
||||||
p.drawImage(
|
if (expandRatio > 0.) {
|
||||||
QRectF(single.x + nameLeft, nameTop, nameWidth, nameHeight),
|
p.setOpacity(expandRatio);
|
||||||
full->nameCache);
|
p.drawImage(QRectF(
|
||||||
|
single.x + nameLeft,
|
||||||
|
nameTop,
|
||||||
|
nameWidth,
|
||||||
|
nameHeight
|
||||||
|
), full->nameCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unread gradient.
|
// Unread gradient.
|
||||||
const auto x = single.x;
|
const auto x = single.x;
|
||||||
const auto userpic = QRectF(
|
const auto userpic = QRectF(
|
||||||
x + layout.photoLeft,
|
x + layout.photoLeft,
|
||||||
photoTop,
|
single.photoTop,
|
||||||
photo,
|
photo,
|
||||||
photo);
|
photo);
|
||||||
const auto small = single.itemSmall;
|
const auto small = single.itemSmall;
|
||||||
|
@ -448,9 +524,9 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto unreadOpacity = (smallUnread && fullUnread)
|
const auto unreadOpacity = (smallUnread && fullUnread)
|
||||||
? 1.
|
? 1.
|
||||||
: smallUnread
|
: smallUnread
|
||||||
? (1. - ratio)
|
? (1. - expandRatio)
|
||||||
: fullUnread
|
: fullUnread
|
||||||
? ratio
|
? expandRatio
|
||||||
: 0.;
|
: 0.;
|
||||||
if (unreadOpacity > 0.) {
|
if (unreadOpacity > 0.) {
|
||||||
p.setOpacity(unreadOpacity);
|
p.setOpacity(unreadOpacity);
|
||||||
|
@ -475,7 +551,7 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto x = single.x;
|
const auto x = single.x;
|
||||||
const auto userpic = QRectF(
|
const auto userpic = QRectF(
|
||||||
x + layout.photoLeft,
|
x + layout.photoLeft,
|
||||||
photoTop,
|
single.photoTop,
|
||||||
photo,
|
photo,
|
||||||
photo);
|
photo);
|
||||||
const auto small = single.itemSmall;
|
const auto small = single.itemSmall;
|
||||||
|
@ -487,7 +563,7 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
const auto hasReadLine = (itemFull && !fullUnread);
|
const auto hasReadLine = (itemFull && !fullUnread);
|
||||||
if (hasReadLine) {
|
if (hasReadLine) {
|
||||||
auto color = st::dialogsUnreadBgMuted->c;
|
auto color = st::dialogsUnreadBgMuted->c;
|
||||||
color.setAlphaF(color.alphaF() * ratio);
|
color.setAlphaF(color.alphaF() * expandRatio);
|
||||||
auto pen = QPen(color);
|
auto pen = QPen(color);
|
||||||
pen.setWidthF(lineRead);
|
pen.setWidthF(lineRead);
|
||||||
p.setPen(pen);
|
p.setPen(pen);
|
||||||
|
@ -508,16 +584,18 @@ void List::paintEvent(QPaintEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
if (small) {
|
if (small) {
|
||||||
p.setOpacity(smallUnread
|
p.setOpacity(smallUnread
|
||||||
? (itemFull ? 1. : (1. - ratio))
|
? (itemFull ? 1. : (1. - expandRatio))
|
||||||
: (itemFull
|
: (itemFull
|
||||||
? _st.readOpacity
|
? _st.readOpacity
|
||||||
: readUserpicAppearingOpacity));
|
: readUserpicAppearingOpacity));
|
||||||
validateThumbnail(small);
|
validateThumbnail(small);
|
||||||
const auto size = (ratio > 0.) ? full.photo : st.photo;
|
const auto size = (expandRatio > 0.)
|
||||||
|
? full.photo
|
||||||
|
: st.photo;
|
||||||
p.drawImage(userpic, small->element.thumbnail->image(size));
|
p.drawImage(userpic, small->element.thumbnail->image(size));
|
||||||
}
|
}
|
||||||
if (itemFull) {
|
if (itemFull) {
|
||||||
p.setOpacity(ratio);
|
p.setOpacity(expandRatio);
|
||||||
validateThumbnail(itemFull);
|
validateThumbnail(itemFull);
|
||||||
const auto size = full.photo;
|
const auto size = full.photo;
|
||||||
p.drawImage(
|
p.drawImage(
|
||||||
|
@ -670,7 +748,7 @@ void List::wheelEvent(QWheelEvent *e) {
|
||||||
const auto used = now - delta;
|
const auto used = now - delta;
|
||||||
const auto next = std::clamp(used, 0, _scrollLeftMax);
|
const auto next = std::clamp(used, 0, _scrollLeftMax);
|
||||||
if (next != now) {
|
if (next != now) {
|
||||||
_toggleExpandedRequests.fire(true);
|
requestExpanded(true);
|
||||||
_scrollLeft = next;
|
_scrollLeft = next;
|
||||||
updateSelected();
|
updateSelected();
|
||||||
checkLoadMore();
|
checkLoadMore();
|
||||||
|
@ -698,7 +776,7 @@ void List::mouseMoveEvent(QMouseEvent *e) {
|
||||||
if ((_lastMousePosition - *_mouseDownPosition).manhattanLength()
|
if ((_lastMousePosition - *_mouseDownPosition).manhattanLength()
|
||||||
>= QApplication::startDragDistance()) {
|
>= QApplication::startDragDistance()) {
|
||||||
if (_shownHeight() < _st.full.height) {
|
if (_shownHeight() < _st.full.height) {
|
||||||
_toggleExpandedRequests.fire(true);
|
requestExpanded(true);
|
||||||
}
|
}
|
||||||
_dragging = true;
|
_dragging = true;
|
||||||
_startDraggingLeft = _scrollLeft;
|
_startDraggingLeft = _scrollLeft;
|
||||||
|
@ -742,7 +820,7 @@ void List::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
updateSelected();
|
updateSelected();
|
||||||
if (_selected == pressed) {
|
if (_selected == pressed) {
|
||||||
if (_selected < 0) {
|
if (_selected < 0) {
|
||||||
_toggleExpandedRequests.fire(true);
|
requestExpanded(true);
|
||||||
} else if (_selected < _data.items.size()) {
|
} else if (_selected < _data.items.size()) {
|
||||||
_clicks.fire_copy(_data.items[_selected].element.id);
|
_clicks.fire_copy(_data.items[_selected].element.id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/qt/qt_compare.h"
|
#include "base/qt/qt_compare.h"
|
||||||
|
#include "base/timer.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
|
@ -148,7 +149,9 @@ private:
|
||||||
void checkDragging();
|
void checkDragging();
|
||||||
bool finishDragging();
|
bool finishDragging();
|
||||||
void checkLoadMore();
|
void checkLoadMore();
|
||||||
|
void requestExpanded(bool expanded);
|
||||||
|
|
||||||
|
void updateExpanding(int minHeight, int shownHeight, int fullHeight);
|
||||||
void updateHeight();
|
void updateHeight();
|
||||||
void toggleAnimated(bool shown);
|
void toggleAnimated(bool shown);
|
||||||
void paintSummary(
|
void paintSummary(
|
||||||
|
@ -157,7 +160,7 @@ private:
|
||||||
float64 summaryTop,
|
float64 summaryTop,
|
||||||
float64 hidden);
|
float64 hidden);
|
||||||
|
|
||||||
[[nodiscard]] Layout computeLayout() const;
|
[[nodiscard]] Layout computeLayout();
|
||||||
|
|
||||||
const style::DialogsStoriesList &_st;
|
const style::DialogsStoriesList &_st;
|
||||||
Content _content;
|
Content _content;
|
||||||
|
@ -181,6 +184,12 @@ private:
|
||||||
int _scrollLeftMax = 0;
|
int _scrollLeftMax = 0;
|
||||||
bool _dragging = false;
|
bool _dragging = false;
|
||||||
|
|
||||||
|
Ui::Animations::Simple _expandedAnimation;
|
||||||
|
base::Timer _snapExpandedTimer;
|
||||||
|
float64 _lastRatio = 0.;
|
||||||
|
int _lastHeight = 0;
|
||||||
|
bool _expanded = false;
|
||||||
|
|
||||||
int _selected = -1;
|
int _selected = -1;
|
||||||
int _pressed = -1;
|
int _pressed = -1;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue