Fixed position of selected X in linear chart animations.

This commit is contained in:
23rd 2023-09-05 17:03:08 +03:00 committed by John Preston
parent 20c2250abb
commit 54d5358b75
9 changed files with 83 additions and 65 deletions

View File

@ -830,20 +830,6 @@ Limits ChartWidget::ChartAnimationController::finalHeightLimits() const {
return _finalHeightLimits;
}
float64 ChartWidget::ChartAnimationController::detailsProgress(
crl::time now,
const Limits &appearedOnXLimits) const {
const auto xLimitsChanged = false
|| (appearedOnXLimits.min != _animationValueXMin.to())
|| (appearedOnXLimits.max != _animationValueXMax.to());
return (_animation.animating() && xLimitsChanged)
? std::clamp(
(now - _animation.started()) / float64(kExpandingDelay),
0.,
1.)
: 0.;
}
bool ChartWidget::ChartAnimationController::animating() const {
return _animation.animating();
}
@ -964,35 +950,6 @@ void ChartWidget::setupChartArea() {
PaintHorizontalLines(p, horizontalLine, chartRect);
}
const auto detailsAlpha = 1.
- _animationController.detailsProgress(
now,
_details.appearedOnXLimits);
if (_details.widget) {
if (!detailsAlpha && _details.currentX) {
_details.widget->hide();
_details.widget->setXIndex(-1);
_details.currentX = 0;
_details.appearedOnXLimits = {};
}
if (_details.currentX) {
const auto lineRect = QRectF(
_details.currentX - (st::lineWidth / 2.),
0,
st::lineWidth,
_chartArea->height());
const auto opacity = ScopedPainterOpacity(p, detailsAlpha);
p.fillRect(lineRect, st::windowSubTextFg);
_details.widget->setAlpha(detailsAlpha);
for (const auto &line : _chartData.lines) {
_details.widget->setLineAlpha(
line.id,
_chartView->alpha(line.id));
}
}
}
if (_chartData) {
// p.setRenderHint(
// QPainter::Antialiasing,
@ -1020,16 +977,22 @@ void ChartWidget::setupChartArea() {
QRect(bottom.x(), bottom.y(), bottom.width(), st::lineWidth),
st::windowSubTextFg);
}
if (_details.widget && (detailsAlpha > 0.)) {
auto hq = PainterHighQualityEnabler(p);
auto o = ScopedPainterOpacity(p, detailsAlpha);
if (_details.widget) {
const auto detailsAlpha = _details.widget->alpha();
for (const auto &line : _chartData.lines) {
_details.widget->setLineAlpha(
line.id,
_chartView->alpha(line.id));
}
_chartView->paintSelectedXIndex(
p,
_chartData,
_animationController.currentXLimits(),
_animationController.currentHeightLimits(),
chartRect,
_details.widget->xIndex());
_details.widget->xIndex(),
detailsAlpha);
}
p.setPen(st::windowSubTextFg);
@ -1158,6 +1121,12 @@ void ChartWidget::setupFooter() {
_footer->xPercentageLimitsChange(
) | rpl::start_with_next([=](Limits xPercentageLimits) {
const auto now = crl::now();
if (_details.widget
&& (_details.widget->xIndex() >= 0)
&& !_details.animation.animating()) {
_details.hideOnAnimationEnd = true;
_details.animation.start();
}
_animationController.setXPercentageLimits(
_chartData,
xPercentageLimits,
@ -1176,7 +1145,7 @@ void ChartWidget::setupFooter() {
void ChartWidget::setupDetails() {
if (!_chartData) {
_details = {};
_details.widget = nullptr;
_chartArea->update();
return;
}
@ -1229,23 +1198,26 @@ void ChartWidget::setupDetails() {
const auto nearestXIndex = std::distance(
begin(_chartData.xPercentage),
nearestXPercentageIt);
_details.currentX = 0
const auto currentX = 0
+ chartRect.width() * InterpolationRatio(
currentXLimits.min,
currentXLimits.max,
*nearestXPercentageIt);
_details.appearedOnXLimits = currentXLimits;
const auto xLeft = _details.currentX
const auto xLeft = currentX
- _details.widget->width();
const auto x = (xLeft >= 0)
? xLeft
: ((_details.currentX
: ((currentX
+ _details.widget->width()
- _chartArea->width()) > 0)
? 0
: _details.currentX;
: currentX;
_details.widget->moveToLeft(x, _chartArea->y());
_details.widget->setXIndex(nearestXIndex);
if (_details.widget->isHidden()) {
_details.hideOnAnimationEnd = false;
_details.animation.start();
}
_details.widget->show();
_chartArea->update();
} break;
@ -1253,6 +1225,26 @@ void ChartWidget::setupDetails() {
} break;
}
}, _details.widget->lifetime());
_details.animation.init([=](crl::time now) {
const auto value = std::clamp(
(now - _details.animation.started()) / float64(200),
0.,
1.);
const auto alpha = _details.hideOnAnimationEnd ? (1. - value) : value;
_chartArea->update();
if (_details.widget) {
_details.widget->setAlpha(alpha);
_details.widget->update();
}
if (value >= 1.) {
if (_details.hideOnAnimationEnd && _details.widget) {
_details.widget->hide();
_details.widget->setXIndex(-1);
}
_details.animation.stop();
}
});
}
void ChartWidget::setupFilterButtons() {

View File

@ -75,9 +75,6 @@ private:
[[nodiscard]] Limits currentHeightLimits() const;
[[nodiscard]] Limits currentFooterHeightLimits() const;
[[nodiscard]] Limits finalHeightLimits() const;
[[nodiscard]] float64 detailsProgress(
crl::time now,
const Limits &appearedOnXLimits) const;
[[nodiscard]] bool animating() const;
[[nodiscard]] bool footerAnimating() const;
[[nodiscard]] bool isFPSSlow() const;
@ -146,8 +143,8 @@ private:
struct {
base::unique_qptr<PointDetailsWidget> widget;
float64 currentX = 0;
Limits appearedOnXLimits;
Ui::Animations::Basic animation;
bool hideOnAnimationEnd = false;
} _details;
struct {

View File

@ -143,6 +143,10 @@ void PointDetailsWidget::setAlpha(float64 alpha) {
update();
}
float64 PointDetailsWidget::alpha() const {
return _alpha;
}
int PointDetailsWidget::lineYAt(int index) const {
auto linesHeight = 0.;
for (auto i = 0; i < index; i++) {
@ -186,7 +190,7 @@ void PointDetailsWidget::paintEvent(QPaintEvent *e) {
.outerWidth = _textRect.width() - valueWidth,
.availableWidth = _textRect.width(),
};
p.setOpacity(line.alpha * line.alpha);
p.setOpacity(line.alpha * line.alpha * _alpha);
p.setPen(st::boxTextFg);
line.name.draw(p, nameContext);
p.setPen(line.valueColor);

View File

@ -23,6 +23,7 @@ public:
[[nodiscard]] int xIndex() const;
void setXIndex(int xIndex);
void setAlpha(float64 alpha);
[[nodiscard]] float64 alpha() const;
void setLineAlpha(int lineId, float64 alpha);
protected:

View File

@ -34,7 +34,8 @@ public:
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
int selectedXIndex) = 0;
int selectedXIndex,
float64 progress) = 0;
virtual void setEnabled(int id, bool enabled, crl::time now) = 0;
[[nodiscard]] virtual bool isEnabled(int id) const = 0;

View File

@ -135,16 +135,22 @@ void LinearChartView::paintSelectedXIndex(
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
int selectedXIndex) {
int selectedXIndex,
float64 progress) {
if (selectedXIndex < 0) {
return;
}
auto hq = PainterHighQualityEnabler(p);
auto o = ScopedPainterOpacity(p, progress);
p.setBrush(st::boxBg);
const auto r = st::statisticsDetailsDotRadius;
const auto i = selectedXIndex;
const auto isSameToken = (_selectedPoints.lastXIndex == selectedXIndex)
&& (_selectedPoints.lastHeightLimits.min == heightLimits.min)
&& (_selectedPoints.lastHeightLimits.max == heightLimits.max);
&& (_selectedPoints.lastHeightLimits.max == heightLimits.max)
&& (_selectedPoints.lastXLimits.min == xPercentageLimits.min)
&& (_selectedPoints.lastXLimits.max == xPercentageLimits.max);
auto linePainted = false;
for (const auto &line : chartData.lines) {
const auto lineAlpha = alpha(line.id);
const auto useCache = isSameToken
@ -161,6 +167,18 @@ void LinearChartView::paintSelectedXIndex(
+ rect.topLeft();
}
if (!linePainted) {
const auto lineRect = QRectF(
rect.x()
+ begin(_selectedPoints.points)->second.x()
- (st::lineWidth / 2.),
rect.y(),
st::lineWidth,
rect.height());
p.fillRect(lineRect, st::windowSubTextFg);
linePainted = true;
}
// Paint.
auto o = ScopedPainterOpacity(p, lineAlpha * p.opacity());
p.setPen(QPen(line.color, st::statisticsChartLineWidth));
@ -168,6 +186,7 @@ void LinearChartView::paintSelectedXIndex(
}
_selectedPoints.lastXIndex = selectedXIndex;
_selectedPoints.lastHeightLimits = heightLimits;
_selectedPoints.lastXLimits = xPercentageLimits;
}
void LinearChartView::setEnabled(int id, bool enabled, crl::time now) {

View File

@ -38,7 +38,8 @@ public:
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
int selectedXIndex) override;
int selectedXIndex,
float64 progress) override;
void setEnabled(int id, bool enabled, crl::time now) override;
[[nodiscard]] bool isEnabled(int id) const override;
@ -97,6 +98,7 @@ private:
struct SelectedPoints final {
int lastXIndex = -1;
Limits lastHeightLimits;
Limits lastXLimits;
base::flat_map<int, QPointF> points;
};
SelectedPoints _selectedPoints;

View File

@ -94,7 +94,8 @@ void StackChartView::paintSelectedXIndex(
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
int selectedXIndex) {
int selectedXIndex,
float64 progress) {
}
void StackChartView::setEnabled(int id, bool enabled, crl::time now) {

View File

@ -39,7 +39,8 @@ public:
const Limits &xPercentageLimits,
const Limits &heightLimits,
const QRect &rect,
int selectedXIndex) override;
int selectedXIndex,
float64 progress) override;
void setEnabled(int id, bool enabled, crl::time now) override;
[[nodiscard]] bool isEnabled(int id) const override;