diff --git a/Telegram/SourceFiles/statistics/chart_widget.cpp b/Telegram/SourceFiles/statistics/chart_widget.cpp index 23154408a4..66067c4834 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.cpp +++ b/Telegram/SourceFiles/statistics/chart_widget.cpp @@ -939,16 +939,12 @@ void ChartWidget::setupChartArea() { } } - auto detailsPaintContext = DetailsPaintContext{ - .xIndex = (_details.widget && (detailsAlpha > 0.)) - ? _details.widget->xIndex() - : -1, - }; if (_chartData) { // p.setRenderHint( // QPainter::Antialiasing, // !_animationController.isFPSSlow() // || !_animationController.animating()); + PainterHighQualityEnabler hp(p); _linearChartView->paint( p, _chartData, @@ -956,7 +952,6 @@ void ChartWidget::setupChartArea() { _animationController.currentXLimits(), _animationController.currentHeightLimits(), chartRect, - detailsPaintContext, false); } @@ -971,13 +966,16 @@ void ChartWidget::setupChartArea() { QRect(bottom.x(), bottom.y(), bottom.width(), st::lineWidth), st::windowSubTextFg); } - for (const auto &dot : detailsPaintContext.dots) { - p.setBrush(st::boxBg); - p.setPen(QPen(dot.color, st::statisticsChartLineWidth)); - const auto r = st::statisticsDetailsDotRadius; + if (_details.widget && (detailsAlpha > 0.)) { auto hq = PainterHighQualityEnabler(p); - auto o = ScopedPainterOpacity(p, dot.alpha * detailsAlpha); - p.drawEllipse(dot.point, r, r); + auto o = ScopedPainterOpacity(p, detailsAlpha); + _linearChartView->paintSelectedXIndex( + p, + _chartData, + _animationController.currentXLimits(), + _animationController.currentHeightLimits(), + chartRect, + _details.widget->xIndex()); } p.setPen(st::windowSubTextFg); @@ -1067,7 +1065,6 @@ void ChartWidget::setupFooter() { QPainter &p, const QRect &r) { if (_chartData) { - auto detailsPaintContext = DetailsPaintContext{ .xIndex = -1 }; p.fillRect(r, st::boxBg); // p.setRenderHint( // QPainter::Antialiasing, @@ -1081,7 +1078,6 @@ void ChartWidget::setupFooter() { fullXLimits, _animationController.currentFooterHeightLimits(), r, - detailsPaintContext, true); } }); diff --git a/Telegram/SourceFiles/statistics/linear_chart_view.cpp b/Telegram/SourceFiles/statistics/linear_chart_view.cpp index d364546f7b..b1807add97 100644 --- a/Telegram/SourceFiles/statistics/linear_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/linear_chart_view.cpp @@ -64,7 +64,6 @@ void LinearChartView::paint( const Limits &xPercentageLimits, const Limits &heightLimits, const QRect &rect, - DetailsPaintContext &detailsPaintContext, bool footer) { const auto cacheToken = LinearChartView::CacheToken( @@ -128,6 +127,47 @@ void LinearChartView::paint( } } +void LinearChartView::paintSelectedXIndex( + QPainter &p, + const Data::StatisticalChart &chartData, + const Limits &xPercentageLimits, + const Limits &heightLimits, + const QRect &rect, + int selectedXIndex) { + if (selectedXIndex < 0) { + return; + } + 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); + for (const auto &line : chartData.lines) { + const auto lineAlpha = alpha(line.id); + const auto useCache = isSameToken + || (lineAlpha < 1. && !isEnabled(line.id)); + if (!useCache) { + // Calculate. + const auto xPoint = rect.width() + * ((chartData.xPercentage[i] - xPercentageLimits.min) + / (xPercentageLimits.max - xPercentageLimits.min)); + const auto yPercentage = (line.y[i] - heightLimits.min) + / float64(heightLimits.max - heightLimits.min); + const auto yPoint = (1. - yPercentage) * rect.height(); + _selectedPoints.points[line.id] = QPointF(xPoint, yPoint) + + rect.topLeft(); + } + + // Paint. + auto o = ScopedPainterOpacity(p, lineAlpha * p.opacity()); + p.setPen(QPen(line.color, st::statisticsChartLineWidth)); + p.drawEllipse(_selectedPoints.points[line.id], r, r); + } + _selectedPoints.lastXIndex = selectedXIndex; + _selectedPoints.lastHeightLimits = heightLimits; +} + void LinearChartView::setEnabled(int id, bool enabled, crl::time now) { const auto it = _entries.find(id); if (it == end(_entries)) { diff --git a/Telegram/SourceFiles/statistics/linear_chart_view.h b/Telegram/SourceFiles/statistics/linear_chart_view.h index 9d59549680..3eaecdcd5b 100644 --- a/Telegram/SourceFiles/statistics/linear_chart_view.h +++ b/Telegram/SourceFiles/statistics/linear_chart_view.h @@ -16,7 +16,6 @@ struct StatisticalChart; namespace Statistic { struct Limits; -struct DetailsPaintContext; class LinearChartView { public: @@ -29,9 +28,16 @@ public: const Limits &xPercentageLimits, const Limits &heightLimits, const QRect &rect, - DetailsPaintContext &detailsPaintContext, bool footer); + void paintSelectedXIndex( + QPainter &p, + const Data::StatisticalChart &chartData, + const Limits &xPercentageLimits, + const Limits &heightLimits, + const QRect &rect, + int selectedXIndex); + void setEnabled(int id, bool enabled, crl::time now); [[nodiscard]] bool isEnabled(int id) const; [[nodiscard]] bool isFinished() const; @@ -82,6 +88,13 @@ private: base::flat_map _mainCaches; base::flat_map _footerCaches; + struct SelectedPoints final { + int lastXIndex = -1; + Limits lastHeightLimits; + base::flat_map points; + }; + SelectedPoints _selectedPoints; + struct Entry final { bool enabled = false; crl::time startedAt = 0; diff --git a/Telegram/SourceFiles/statistics/statistics_common.h b/Telegram/SourceFiles/statistics/statistics_common.h index 1c9beeac8c..397791c572 100644 --- a/Telegram/SourceFiles/statistics/statistics_common.h +++ b/Telegram/SourceFiles/statistics/statistics_common.h @@ -14,16 +14,4 @@ struct Limits final { float64 max = 0; }; -// Dot on line charts. -struct DetailsPaintContext final { - int xIndex = -1; - - struct Dot { - QPointF point; - QColor color; - float64 alpha = 0.; - }; - std::vector dots; -}; - } // namespace Statistic