From e6559276c0899ba6a119e4d70eff1f9fe2968cf5 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 14 Jul 2023 07:25:17 +0300 Subject: [PATCH] Added class to calculate context state while chart lines are filtering. --- Telegram/CMakeLists.txt | 2 + .../statistics/chart_line_view_context.cpp | 68 +++++++++++++++++++ .../statistics/chart_line_view_context.h | 35 ++++++++++ .../SourceFiles/statistics/chart_widget.cpp | 50 +++----------- .../SourceFiles/statistics/chart_widget.h | 7 +- .../statistics/linear_chart_view.cpp | 12 ++-- .../statistics/linear_chart_view.h | 2 +- .../statistics/statistics_common.h | 7 -- 8 files changed, 125 insertions(+), 58 deletions(-) create mode 100644 Telegram/SourceFiles/statistics/chart_line_view_context.cpp create mode 100644 Telegram/SourceFiles/statistics/chart_line_view_context.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 00d68e1a3..987f8db08 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1284,6 +1284,8 @@ PRIVATE settings/settings_websites.h statistics/chart_horizontal_lines_data.cpp statistics/chart_horizontal_lines_data.h + statistics/chart_line_view_context.cpp + statistics/chart_line_view_context.h statistics/chart_widget.cpp statistics/chart_widget.h statistics/linear_chart_view.cpp diff --git a/Telegram/SourceFiles/statistics/chart_line_view_context.cpp b/Telegram/SourceFiles/statistics/chart_line_view_context.cpp new file mode 100644 index 000000000..1d3e7a9f8 --- /dev/null +++ b/Telegram/SourceFiles/statistics/chart_line_view_context.cpp @@ -0,0 +1,68 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "statistics/chart_line_view_context.h" + +namespace Statistic { +namespace { +constexpr auto kAlphaDuration = float64(200); +} // namespace + +void ChartLineViewContext::setEnabled(int id, bool enabled, crl::time now) { + const auto it = _entries.find(id); + if (it == end(_entries)) { + _entries[id] = Entry{ .enabled = enabled, .startedAt = now }; + } else if (it->second.enabled != enabled) { + auto &entry = it->second; + entry.enabled = enabled; + entry.startedAt = now + - kAlphaDuration * (enabled ? entry.alpha : (1. - entry.alpha)); + } + _isFinished = false; +} + +bool ChartLineViewContext::isFinished() const { + return _isFinished; +} + +bool ChartLineViewContext::isEnabled(int id) const { + const auto it = _entries.find(id); + return (it == end(_entries)) ? true : it->second.enabled; +} + +float64 ChartLineViewContext::alpha(int id) const { + const auto it = _entries.find(id); + return (it == end(_entries)) ? 1. : it->second.alpha; +} + +void ChartLineViewContext::tick(crl::time now) { + auto finishedCount = 0; + auto idsToRemove = std::vector(); + for (auto &[id, entry] : _entries) { + if (!entry.startedAt) { + continue; + } + const auto progress = (now - entry.startedAt) / kAlphaDuration; + entry.alpha = std::clamp( + entry.enabled ? progress : (1. - progress), + 0., + 1.); + if (entry.alpha == 1.) { + idsToRemove.push_back(id); + } + if (progress >= 1.) { + finishedCount++; + } + } + _isFinished = (finishedCount == _entries.size()); + for (const auto &id : idsToRemove) { + _entries.remove(id); + } +} + + +} // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/chart_line_view_context.h b/Telegram/SourceFiles/statistics/chart_line_view_context.h new file mode 100644 index 000000000..506763ac6 --- /dev/null +++ b/Telegram/SourceFiles/statistics/chart_line_view_context.h @@ -0,0 +1,35 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +namespace Statistic { + +class ChartLineViewContext final { +public: + ChartLineViewContext() = default; + + void setEnabled(int id, bool enabled, crl::time now); + [[nodiscard]] bool isFinished() const; + [[nodiscard]] bool isEnabled(int id) const; + [[nodiscard]] float64 alpha(int id) const; + + void tick(crl::time now); + +private: + struct Entry final { + bool enabled = false; + crl::time startedAt = 0; + float64 alpha = 1.; + }; + + base::flat_map _entries; + bool _isFinished = true; + +}; + +} // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/chart_widget.cpp b/Telegram/SourceFiles/statistics/chart_widget.cpp index 087010233..446fad40d 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.cpp +++ b/Telegram/SourceFiles/statistics/chart_widget.cpp @@ -529,11 +529,12 @@ ChartWidget::ChartAnimationController::ChartAnimationController( void ChartWidget::ChartAnimationController::setXPercentageLimits( Data::StatisticalChart &chartData, Limits xPercentageLimits, - std::vector &chartLinesViewContext, + const ChartLineViewContext &chartLinesViewContext, crl::time now) { if ((_animationValueXMin.to() == xPercentageLimits.min) - && (_animationValueXMax.to() == xPercentageLimits.max)) { - // return; + && (_animationValueXMax.to() == xPercentageLimits.max) + && chartLinesViewContext.isFinished()) { + return; } start(); _animationValueXMin.start(xPercentageLimits.min); @@ -556,10 +557,7 @@ void ChartWidget::ChartAnimationController::setXPercentageLimits( auto minValue = std::numeric_limits::max(); auto maxValue = 0; for (auto &l : chartData.lines) { - const auto it = ranges::find_if(chartLinesViewContext, [&](const auto &a) { - return a.id == l.id; - }); - if (it != end(chartLinesViewContext) && !it->enabled) { + if (!chartLinesViewContext.isEnabled(l.id)) { continue; } const auto lineMax = l.segmentTree.rMaxQ(startXIndex, endXIndex); @@ -633,7 +631,7 @@ void ChartWidget::ChartAnimationController::tick( crl::time now, std::vector &horizontalLines, std::vector &dateLines, - std::vector &chartLinesViewContext) { + ChartLineViewContext &chartLinesViewContext) { if (!_animation.animating()) { return; } @@ -690,33 +688,13 @@ void ChartWidget::ChartAnimationController::tick( const auto bottomLineAlphaFinished = isFinished( _animValueBottomLineAlpha); - auto chartLinesViewContextFinished = false; - { - auto finishedCount = 0; - for (auto &viewLine : chartLinesViewContext) { - if (!viewLine.startedAt) { - continue; - } - const auto progress = (now - viewLine.startedAt) - / (kXExpandingDuration * 2); - viewLine.alpha = std::clamp( - viewLine.enabled ? progress : (1. - progress), - 0., - 1.); - if (progress >= 1.) { - finishedCount++; - } - } - chartLinesViewContextFinished = - (finishedCount == chartLinesViewContext.size()); - } - + chartLinesViewContext.tick(now); if (xFinished && yFinished && alphaFinished && bottomLineAlphaFinished - && chartLinesViewContextFinished) { + && chartLinesViewContext.isFinished()) { const auto &lines = horizontalLines.back().lines; if ((lines.front().absoluteValue == _animationValueHeightMin.to()) && lines.back().absoluteValue == _animationValueHeightMax.to()) { @@ -1212,20 +1190,14 @@ void ChartWidget::setupFilterButtons() { _filterButtons->buttonEnabledChanges( ) | rpl::start_with_next([=](const ChartLinesFilterWidget::Entry &e) { - auto data = ChartLineViewContext{ - .id = e.id, - .enabled = e.enabled, - .startedAt = crl::now(), - }; - _animatedChartLines.clear(); - _animatedChartLines.push_back(data); + const auto now = crl::now(); + _animatedChartLines.setEnabled(e.id, e.enabled, now); _animationController.setXPercentageLimits( _chartData, _animationController.currentXLimits(), _animatedChartLines, - data.startedAt); - + now); }, _filterButtons->lifetime()); } diff --git a/Telegram/SourceFiles/statistics/chart_widget.h b/Telegram/SourceFiles/statistics/chart_widget.h index 379728c06..700f0fed1 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.h +++ b/Telegram/SourceFiles/statistics/chart_widget.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_statistics.h" #include "statistics/chart_horizontal_lines_data.h" +#include "statistics/chart_line_view_context.h" #include "statistics/statistics_common.h" #include "ui/effects/animation_value.h" #include "ui/effects/animations.h" @@ -48,7 +49,7 @@ private: void setXPercentageLimits( Data::StatisticalChart &chartData, Limits xPercentageLimits, - std::vector &chartLinesViewContext, + const ChartLineViewContext &chartLinesViewContext, crl::time now); void start(); void finish(); @@ -58,7 +59,7 @@ private: crl::time now, std::vector &horizontalLines, std::vector &dateLines, - std::vector &chartLinesViewContext); + ChartLineViewContext &chartLinesViewContext); [[nodiscard]] Limits currentXLimits() const; [[nodiscard]] Limits currentXIndices() const; @@ -119,7 +120,7 @@ private: base::unique_qptr _filterButtons; Data::StatisticalChart _chartData; - std::vector _animatedChartLines; + ChartLineViewContext _animatedChartLines; struct { base::unique_qptr widget; diff --git a/Telegram/SourceFiles/statistics/linear_chart_view.cpp b/Telegram/SourceFiles/statistics/linear_chart_view.cpp index d5905c170..472694bbb 100644 --- a/Telegram/SourceFiles/statistics/linear_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/linear_chart_view.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "statistics/linear_chart_view.h" #include "data/data_statistics.h" +#include "statistics/chart_line_view_context.h" #include "statistics/statistics_common.h" #include "ui/effects/animation_value_f.h" #include "ui/painter.h" @@ -23,19 +24,13 @@ void PaintLinearChartView( const Limits &xPercentageLimits, const Limits &heightLimits, const QRect &rect, - const std::vector &linesContext, + const ChartLineViewContext &lineViewContext, DetailsPaintContext &detailsPaintContext) { const auto currentMinHeight = rect.y(); // const auto currentMaxHeight = rect.height() + rect.y(); // for (const auto &line : chartData.lines) { - p.setOpacity(1.); - for (const auto &lineContext : linesContext) { - if (lineContext.id == line.id) { - p.setOpacity(lineContext.alpha); - break; - } - } + p.setOpacity(lineViewContext.alpha(line.id)); if (!p.opacity()) { continue; } @@ -78,6 +73,7 @@ void PaintLinearChartView( p.drawPath(chartPath); } p.setPen(st::boxTextFg); + p.setOpacity(1.); } } // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/linear_chart_view.h b/Telegram/SourceFiles/statistics/linear_chart_view.h index d0484c87c..8460a8bc2 100644 --- a/Telegram/SourceFiles/statistics/linear_chart_view.h +++ b/Telegram/SourceFiles/statistics/linear_chart_view.h @@ -24,7 +24,7 @@ void PaintLinearChartView( const Limits &xPercentageLimits, const Limits &heightLimits, const QRect &rect, - const std::vector &linesContext, + const ChartLineViewContext &lineViewContext, DetailsPaintContext &detailsPaintContext); } // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/statistics_common.h b/Telegram/SourceFiles/statistics/statistics_common.h index a655a2575..ac1d95089 100644 --- a/Telegram/SourceFiles/statistics/statistics_common.h +++ b/Telegram/SourceFiles/statistics/statistics_common.h @@ -25,11 +25,4 @@ struct DetailsPaintContext final { std::vector dots; }; -struct ChartLineViewContext final { - int id = 0; - bool enabled = false; - crl::time startedAt = 0; - float64 alpha = 1.; -}; - } // namespace Statistic