Added class to calculate context state while chart lines are filtering.

This commit is contained in:
23rd 2023-07-14 07:25:17 +03:00 committed by John Preston
parent 13959ca36c
commit e6559276c0
8 changed files with 125 additions and 58 deletions

View file

@ -1284,6 +1284,8 @@ PRIVATE
settings/settings_websites.h settings/settings_websites.h
statistics/chart_horizontal_lines_data.cpp statistics/chart_horizontal_lines_data.cpp
statistics/chart_horizontal_lines_data.h 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.cpp
statistics/chart_widget.h statistics/chart_widget.h
statistics/linear_chart_view.cpp statistics/linear_chart_view.cpp

View file

@ -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<int>();
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

View file

@ -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<int, Entry> _entries;
bool _isFinished = true;
};
} // namespace Statistic

View file

@ -529,11 +529,12 @@ ChartWidget::ChartAnimationController::ChartAnimationController(
void ChartWidget::ChartAnimationController::setXPercentageLimits( void ChartWidget::ChartAnimationController::setXPercentageLimits(
Data::StatisticalChart &chartData, Data::StatisticalChart &chartData,
Limits xPercentageLimits, Limits xPercentageLimits,
std::vector<ChartLineViewContext> &chartLinesViewContext, const ChartLineViewContext &chartLinesViewContext,
crl::time now) { crl::time now) {
if ((_animationValueXMin.to() == xPercentageLimits.min) if ((_animationValueXMin.to() == xPercentageLimits.min)
&& (_animationValueXMax.to() == xPercentageLimits.max)) { && (_animationValueXMax.to() == xPercentageLimits.max)
// return; && chartLinesViewContext.isFinished()) {
return;
} }
start(); start();
_animationValueXMin.start(xPercentageLimits.min); _animationValueXMin.start(xPercentageLimits.min);
@ -556,10 +557,7 @@ void ChartWidget::ChartAnimationController::setXPercentageLimits(
auto minValue = std::numeric_limits<int>::max(); auto minValue = std::numeric_limits<int>::max();
auto maxValue = 0; auto maxValue = 0;
for (auto &l : chartData.lines) { for (auto &l : chartData.lines) {
const auto it = ranges::find_if(chartLinesViewContext, [&](const auto &a) { if (!chartLinesViewContext.isEnabled(l.id)) {
return a.id == l.id;
});
if (it != end(chartLinesViewContext) && !it->enabled) {
continue; continue;
} }
const auto lineMax = l.segmentTree.rMaxQ(startXIndex, endXIndex); const auto lineMax = l.segmentTree.rMaxQ(startXIndex, endXIndex);
@ -633,7 +631,7 @@ void ChartWidget::ChartAnimationController::tick(
crl::time now, crl::time now,
std::vector<ChartHorizontalLinesData> &horizontalLines, std::vector<ChartHorizontalLinesData> &horizontalLines,
std::vector<BottomCaptionLineData> &dateLines, std::vector<BottomCaptionLineData> &dateLines,
std::vector<ChartLineViewContext> &chartLinesViewContext) { ChartLineViewContext &chartLinesViewContext) {
if (!_animation.animating()) { if (!_animation.animating()) {
return; return;
} }
@ -690,33 +688,13 @@ void ChartWidget::ChartAnimationController::tick(
const auto bottomLineAlphaFinished = isFinished( const auto bottomLineAlphaFinished = isFinished(
_animValueBottomLineAlpha); _animValueBottomLineAlpha);
auto chartLinesViewContextFinished = false; chartLinesViewContext.tick(now);
{
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());
}
if (xFinished if (xFinished
&& yFinished && yFinished
&& alphaFinished && alphaFinished
&& bottomLineAlphaFinished && bottomLineAlphaFinished
&& chartLinesViewContextFinished) { && chartLinesViewContext.isFinished()) {
const auto &lines = horizontalLines.back().lines; const auto &lines = horizontalLines.back().lines;
if ((lines.front().absoluteValue == _animationValueHeightMin.to()) if ((lines.front().absoluteValue == _animationValueHeightMin.to())
&& lines.back().absoluteValue == _animationValueHeightMax.to()) { && lines.back().absoluteValue == _animationValueHeightMax.to()) {
@ -1212,20 +1190,14 @@ void ChartWidget::setupFilterButtons() {
_filterButtons->buttonEnabledChanges( _filterButtons->buttonEnabledChanges(
) | rpl::start_with_next([=](const ChartLinesFilterWidget::Entry &e) { ) | rpl::start_with_next([=](const ChartLinesFilterWidget::Entry &e) {
auto data = ChartLineViewContext{ const auto now = crl::now();
.id = e.id, _animatedChartLines.setEnabled(e.id, e.enabled, now);
.enabled = e.enabled,
.startedAt = crl::now(),
};
_animatedChartLines.clear();
_animatedChartLines.push_back(data);
_animationController.setXPercentageLimits( _animationController.setXPercentageLimits(
_chartData, _chartData,
_animationController.currentXLimits(), _animationController.currentXLimits(),
_animatedChartLines, _animatedChartLines,
data.startedAt); now);
}, _filterButtons->lifetime()); }, _filterButtons->lifetime());
} }

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_statistics.h" #include "data/data_statistics.h"
#include "statistics/chart_horizontal_lines_data.h" #include "statistics/chart_horizontal_lines_data.h"
#include "statistics/chart_line_view_context.h"
#include "statistics/statistics_common.h" #include "statistics/statistics_common.h"
#include "ui/effects/animation_value.h" #include "ui/effects/animation_value.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
@ -48,7 +49,7 @@ private:
void setXPercentageLimits( void setXPercentageLimits(
Data::StatisticalChart &chartData, Data::StatisticalChart &chartData,
Limits xPercentageLimits, Limits xPercentageLimits,
std::vector<ChartLineViewContext> &chartLinesViewContext, const ChartLineViewContext &chartLinesViewContext,
crl::time now); crl::time now);
void start(); void start();
void finish(); void finish();
@ -58,7 +59,7 @@ private:
crl::time now, crl::time now,
std::vector<ChartHorizontalLinesData> &horizontalLines, std::vector<ChartHorizontalLinesData> &horizontalLines,
std::vector<BottomCaptionLineData> &dateLines, std::vector<BottomCaptionLineData> &dateLines,
std::vector<ChartLineViewContext> &chartLinesViewContext); ChartLineViewContext &chartLinesViewContext);
[[nodiscard]] Limits currentXLimits() const; [[nodiscard]] Limits currentXLimits() const;
[[nodiscard]] Limits currentXIndices() const; [[nodiscard]] Limits currentXIndices() const;
@ -119,7 +120,7 @@ private:
base::unique_qptr<ChartLinesFilterWidget> _filterButtons; base::unique_qptr<ChartLinesFilterWidget> _filterButtons;
Data::StatisticalChart _chartData; Data::StatisticalChart _chartData;
std::vector<ChartLineViewContext> _animatedChartLines; ChartLineViewContext _animatedChartLines;
struct { struct {
base::unique_qptr<PointDetailsWidget> widget; base::unique_qptr<PointDetailsWidget> widget;

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "statistics/linear_chart_view.h" #include "statistics/linear_chart_view.h"
#include "data/data_statistics.h" #include "data/data_statistics.h"
#include "statistics/chart_line_view_context.h"
#include "statistics/statistics_common.h" #include "statistics/statistics_common.h"
#include "ui/effects/animation_value_f.h" #include "ui/effects/animation_value_f.h"
#include "ui/painter.h" #include "ui/painter.h"
@ -23,19 +24,13 @@ void PaintLinearChartView(
const Limits &xPercentageLimits, const Limits &xPercentageLimits,
const Limits &heightLimits, const Limits &heightLimits,
const QRect &rect, const QRect &rect,
const std::vector<ChartLineViewContext> &linesContext, const ChartLineViewContext &lineViewContext,
DetailsPaintContext &detailsPaintContext) { DetailsPaintContext &detailsPaintContext) {
const auto currentMinHeight = rect.y(); // const auto currentMinHeight = rect.y(); //
const auto currentMaxHeight = rect.height() + rect.y(); // const auto currentMaxHeight = rect.height() + rect.y(); //
for (const auto &line : chartData.lines) { for (const auto &line : chartData.lines) {
p.setOpacity(1.); p.setOpacity(lineViewContext.alpha(line.id));
for (const auto &lineContext : linesContext) {
if (lineContext.id == line.id) {
p.setOpacity(lineContext.alpha);
break;
}
}
if (!p.opacity()) { if (!p.opacity()) {
continue; continue;
} }
@ -78,6 +73,7 @@ void PaintLinearChartView(
p.drawPath(chartPath); p.drawPath(chartPath);
} }
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
p.setOpacity(1.);
} }
} // namespace Statistic } // namespace Statistic

View file

@ -24,7 +24,7 @@ void PaintLinearChartView(
const Limits &xPercentageLimits, const Limits &xPercentageLimits,
const Limits &heightLimits, const Limits &heightLimits,
const QRect &rect, const QRect &rect,
const std::vector<ChartLineViewContext> &linesContext, const ChartLineViewContext &lineViewContext,
DetailsPaintContext &detailsPaintContext); DetailsPaintContext &detailsPaintContext);
} // namespace Statistic } // namespace Statistic

View file

@ -25,11 +25,4 @@ struct DetailsPaintContext final {
std::vector<Dot> dots; std::vector<Dot> dots;
}; };
struct ChartLineViewContext final {
int id = 0;
bool enabled = false;
crl::time startedAt = 0;
float64 alpha = 1.;
};
} // namespace Statistic } // namespace Statistic