From d13fe39629e33a14e3b562005920cda275c1aed8 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 11 Sep 2023 18:10:30 +0300 Subject: [PATCH] Added ability to paint horizontal lines for double linear charts. --- .../chart_horizontal_lines_data.cpp | 22 ++++++-- .../statistics/chart_horizontal_lines_data.h | 5 +- .../view/chart_horizontal_lines_view.cpp | 53 +++++++++++++++---- .../view/chart_horizontal_lines_view.h | 7 ++- 4 files changed, 71 insertions(+), 16 deletions(-) diff --git a/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.cpp b/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.cpp index 3ea4c7dcb4..3936697f11 100644 --- a/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.cpp +++ b/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.cpp @@ -21,12 +21,19 @@ constexpr auto kStep = 5.; return (k % 10 == 0) ? maxValue : ((maxValue / 10 + 1) * 10); } +[[nodiscard]] QString Format(int absoluteValue) { + return (absoluteValue >= 10'000) + ? Lang::FormatCountToShort(absoluteValue).string + : QString("%L1").arg(absoluteValue); +} + } // namespace ChartHorizontalLinesData::ChartHorizontalLinesData( int newMaxHeight, int newMinHeight, - bool useMinHeight) { + bool useMinHeight, + float64 rightRatio) { if (!useMinHeight) { const auto v = (newMaxHeight > 100) ? Round(newMaxHeight) @@ -78,14 +85,21 @@ ChartHorizontalLinesData::ChartHorizontalLinesData( lines.resize(n); const auto diffAbsoluteValue = int((n - 1) * step); + const auto skipFloatValues = (step / rightRatio) < 1; for (auto i = 0; i < n; i++) { auto &line = lines[i]; const auto value = int(i * step); line.absoluteValue = newMinHeight + value; line.relativeValue = 1. - value / float64(diffAbsoluteValue); - line.caption = (line.absoluteValue >= 10'000) - ? Lang::FormatCountToShort(line.absoluteValue).string - : QString("%L1").arg(line.absoluteValue); + line.caption = Format(line.absoluteValue); + if (rightRatio > 0) { + const auto v = (newMinHeight + i * step) / rightRatio; + line.scaledLineCaption = (!skipFloatValues) + ? Format(v) + : ((v - int(v)) < 0.01) + ? Format(v) + : QString(); + } } } } diff --git a/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.h b/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.h index 26589473e8..86f856b691 100644 --- a/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.h +++ b/Telegram/SourceFiles/statistics/chart_horizontal_lines_data.h @@ -14,7 +14,8 @@ public: ChartHorizontalLinesData( int newMaxHeight, int newMinHeight, - bool useMinHeight); + bool useMinHeight, + float64 rightRatio); void computeRelative( int newMaxHeight, @@ -26,6 +27,8 @@ public: float64 absoluteValue = 0.; float64 relativeValue = 0.; QString caption; + QString scaledLineCaption; + float64 rightCaptionWidth = 0.; }; std::vector lines; diff --git a/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.cpp b/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.cpp index d52e6aa052..3f71a4bf24 100644 --- a/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.cpp +++ b/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.cpp @@ -18,10 +18,21 @@ ChartHorizontalLinesView::ChartHorizontalLinesView() = default; void ChartHorizontalLinesView::setChartData( const Data::StatisticalChart &chartData, ChartViewType type) { + _horizontalLines.clear(); _isDouble = (type == ChartViewType::DoubleLinear); if (_isDouble && (chartData.lines.size() == 2)) { - _leftColor = chartData.lines.front().color; - _rightColor = chartData.lines.back().color; + _leftPen = QPen(chartData.lines.front().color); + _rightPen = QPen(chartData.lines.back().color); + + const auto firstMax = chartData.lines.front().maxValue; + const auto secondMax = chartData.lines.back().maxValue; + if (firstMax > secondMax) { + _isLeftLineScaled = false; + _scaledLineRatio = firstMax / float64(secondMax); + } else { + _isLeftLineScaled = true; + _scaledLineRatio = secondMax / float64(firstMax); + } } } @@ -46,16 +57,31 @@ void ChartHorizontalLinesView::paintHorizontalLines( void ChartHorizontalLinesView::paintCaptionsToHorizontalLines( QPainter &p, const QRect &r) { + const auto offset = r.y() - st::statisticsChartHorizontalLineCaptionSkip; + p.setFont(st::statisticsDetailsBottomCaptionStyle.font); for (auto &horizontalLine : _horizontalLines) { const auto alpha = p.opacity(); p.setOpacity(horizontalLine.alpha); - p.setFont(st::statisticsDetailsBottomCaptionStyle.font); - p.setPen(st::windowSubTextFg); - const auto offset = r.y() - - st::statisticsChartHorizontalLineCaptionSkip; for (const auto &line : horizontalLine.lines) { const auto y = offset + r.height() * line.relativeValue; - p.drawText(0, y, line.caption); + p.setPen(_isDouble ? _leftPen : st::windowSubTextFg); + p.drawText( + 0, + y, + (!_isDouble) + ? line.caption + : _isLeftLineScaled + ? line.scaledLineCaption + : line.caption); + if (_isDouble) { + p.setPen(_rightPen); + p.drawText( + r.width() - line.rightCaptionWidth, + y, + _isLeftLineScaled + ? line.caption + : line.scaledLineCaption); + } } p.setOpacity(alpha); } @@ -87,10 +113,19 @@ void ChartHorizontalLinesView::setAlpha(float64 value) { } void ChartHorizontalLinesView::add(Limits newHeight, bool animated) { - const auto newLinesData = ChartHorizontalLinesData( + auto newLinesData = ChartHorizontalLinesData( newHeight.max, newHeight.min, - true); + true, + _isDouble ? _scaledLineRatio : 0.); + if (_isDouble) { + const auto &font = st::statisticsDetailsBottomCaptionStyle.font; + for (auto &line : newLinesData.lines) { + line.rightCaptionWidth = font->width(_isLeftLineScaled + ? line.caption + : line.scaledLineCaption); + } + } if (!animated) { _horizontalLines.clear(); } diff --git a/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.h b/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.h index f8ad7b419d..abe4bfc7d1 100644 --- a/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.h +++ b/Telegram/SourceFiles/statistics/view/chart_horizontal_lines_view.h @@ -36,11 +36,14 @@ public: private: bool _isDouble = false; - QColor _leftColor; - QColor _rightColor; + QPen _leftPen; + QPen _rightPen; std::vector _horizontalLines; + float64 _scaledLineRatio = 0.; + bool _isLeftLineScaled = false; + }; } // namespace Statistic