mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-19 07:37:11 +02:00
Slightly refactored code for statistical charts.
This commit is contained in:
parent
af0e11a1aa
commit
cb4c629178
7 changed files with 41 additions and 66 deletions
|
@ -29,14 +29,14 @@ void StatisticalChart::measure() {
|
|||
}
|
||||
}
|
||||
|
||||
for (auto i = 0; i < lines.size(); i++) {
|
||||
if (lines[i].maxValue > maxValue) {
|
||||
maxValue = lines[i].maxValue;
|
||||
for (auto &line : lines) {
|
||||
if (line.maxValue > maxValue) {
|
||||
maxValue = line.maxValue;
|
||||
}
|
||||
if (lines[i].minValue < minValue) {
|
||||
minValue = lines[i].minValue;
|
||||
if (line.minValue < minValue) {
|
||||
minValue = line.minValue;
|
||||
}
|
||||
lines[i].segmentTree = Statistic::SegmentTree(lines[i].y);
|
||||
line.segmentTree = Statistic::SegmentTree(line.y);
|
||||
}
|
||||
|
||||
daysLookup.clear();
|
||||
|
|
|
@ -7,7 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "statistics/chart_widget.h"
|
||||
|
||||
#include "ui/effects/show_animation.h"
|
||||
#include "base/qt/qt_key_modifiers.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "statistics/chart_header_widget.h"
|
||||
|
@ -19,14 +18,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "statistics/view/stack_chart_common.h"
|
||||
#include "ui/abstract_button.h"
|
||||
#include "ui/effects/animation_value_f.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/effects/show_animation.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/rect.h"
|
||||
#include "ui/round_rect.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_boxes.h"
|
||||
#include "styles/style_statistics.h"
|
||||
|
||||
namespace Statistic {
|
||||
|
@ -34,7 +32,6 @@ namespace Statistic {
|
|||
namespace {
|
||||
|
||||
constexpr auto kHeightLimitsUpdateTimeout = crl::time(320);
|
||||
constexpr auto kExpandingDelay = crl::time(1);
|
||||
|
||||
inline float64 InterpolationRatio(float64 from, float64 to, float64 result) {
|
||||
return (result - from) / (to - from);
|
||||
|
@ -78,10 +75,6 @@ void FillLineColorsByKey(Data::StatisticalChart &chartData) {
|
|||
+ chartData.getDayString(limits.max);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsChartHasLocalZoom(ChartViewType type) {
|
||||
return type == ChartViewType::StackLinear;
|
||||
}
|
||||
|
||||
void PaintBottomLine(
|
||||
QPainter &p,
|
||||
const std::vector<ChartWidget::BottomCaptionLineData> &dates,
|
||||
|
@ -213,13 +206,12 @@ class ChartWidget::Footer final : public RpMouseWidget {
|
|||
public:
|
||||
using PaintCallback = Fn<void(QPainter &, const QRect &)>;
|
||||
|
||||
Footer(not_null<Ui::RpWidget*> parent);
|
||||
explicit Footer(not_null<Ui::RpWidget*> parent);
|
||||
|
||||
void setXPercentageLimits(const Limits &xLimits);
|
||||
|
||||
[[nodiscard]] Limits xPercentageLimits() const;
|
||||
[[nodiscard]] rpl::producer<Limits> xPercentageLimitsChange() const;
|
||||
[[nodiscard]] rpl::producer<> userInteractionFinished() const;
|
||||
|
||||
void setPaintChartCallback(PaintCallback paintChartCallback);
|
||||
|
||||
|
@ -228,7 +220,6 @@ protected:
|
|||
|
||||
private:
|
||||
rpl::event_stream<Limits> _xPercentageLimitsChange;
|
||||
rpl::event_stream<> _userInteractionFinished;
|
||||
|
||||
void prepareCache(int height);
|
||||
|
||||
|
@ -338,7 +329,6 @@ ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent)
|
|||
case QEvent::MouseButtonRelease: {
|
||||
const auto finish = [=] {
|
||||
_dragArea = DragArea::None;
|
||||
_userInteractionFinished.fire({});
|
||||
fire();
|
||||
};
|
||||
if ((_dragArea == DragArea::None) && !_draggedAfterPress) {
|
||||
|
@ -456,11 +446,6 @@ void ChartWidget::Footer::paintEvent(QPaintEvent *e) {
|
|||
const auto innerMargins = QMargins{ 0, lineWidth, 0, lineWidth };
|
||||
const auto r = rect();
|
||||
const auto innerRect = r - innerMargins;
|
||||
const auto inactiveLeftRect = Rect(QSizeF(_leftSide.max, r.height()))
|
||||
- innerMargins;
|
||||
const auto inactiveRightRect = r
|
||||
- QMarginsF{ _rightSide.min, 0, 0, 0 }
|
||||
- innerMargins;
|
||||
const auto &inactiveColor = st::statisticsChartInactive;
|
||||
|
||||
_frame.fill(Qt::transparent);
|
||||
|
@ -524,10 +509,6 @@ rpl::producer<Limits> ChartWidget::Footer::xPercentageLimitsChange() const {
|
|||
return _xPercentageLimitsChange.events();
|
||||
}
|
||||
|
||||
rpl::producer<> ChartWidget::Footer::userInteractionFinished() const {
|
||||
return _userInteractionFinished.events();
|
||||
}
|
||||
|
||||
ChartWidget::ChartAnimationController::ChartAnimationController(
|
||||
Fn<void()> &&updateCallback)
|
||||
: _animation(std::move(updateCallback)) {
|
||||
|
@ -830,10 +811,6 @@ bool ChartWidget::ChartAnimationController::footerAnimating() const {
|
|||
!= _animationValueFooterHeightMax.to());
|
||||
}
|
||||
|
||||
bool ChartWidget::ChartAnimationController::isFPSSlow() const {
|
||||
return _benchmark.lastFPSSlow;
|
||||
}
|
||||
|
||||
ChartWidget::ChartWidget(not_null<Ui::RpWidget*> parent)
|
||||
: Ui::RpWidget(parent)
|
||||
, _chartArea(base::make_unique_q<RpMouseWidget>(this))
|
||||
|
|
|
@ -83,7 +83,6 @@ private:
|
|||
[[nodiscard]] Limits finalHeightLimits() const;
|
||||
[[nodiscard]] bool animating() const;
|
||||
[[nodiscard]] bool footerAnimating() const;
|
||||
[[nodiscard]] bool isFPSSlow() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<> addHorizontalLineRequests() const;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ void SegmentTree::build(int v, int from, int size) {
|
|||
_heap[v].max = _array[from];
|
||||
_heap[v].min = _array[from];
|
||||
} else {
|
||||
// Build childs.
|
||||
// Build children.
|
||||
build(2 * v, from, size / 2);
|
||||
build(2 * v + 1, from + size / 2, size - size / 2);
|
||||
|
||||
|
|
|
@ -21,19 +21,4 @@ enum class ChartViewType {
|
|||
StackLinear,
|
||||
};
|
||||
|
||||
[[nodiscard]] inline Limits FindNearestElements(
|
||||
const std::vector<float64> &vector,
|
||||
const Limits &limit) {
|
||||
const auto find = [&](float64 raw) -> float64 {
|
||||
const auto it = ranges::lower_bound(vector, raw);
|
||||
const auto left = raw - (*(it - 1));
|
||||
const auto right = (*it) - raw;
|
||||
const auto nearestXPercentageIt = ((right) > (left)) ? (it - 1) : it;
|
||||
return std::distance(
|
||||
begin(vector),
|
||||
nearestXPercentageIt);
|
||||
};
|
||||
return { find(limit.min), find(limit.max) };
|
||||
}
|
||||
|
||||
} // namespace Statistic
|
||||
|
|
|
@ -18,7 +18,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
namespace Statistic {
|
||||
namespace {
|
||||
|
||||
float64 Ratio(const LinearChartView::CachedLineRatios &ratios, int id) {
|
||||
[[nodiscard]] float64 Ratio(
|
||||
const LinearChartView::CachedLineRatios &ratios,
|
||||
int id) {
|
||||
return (id == 1) ? ratios.first : ratios.second;
|
||||
}
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ auto StackLinearChartView::partsPercentage(
|
|||
|
||||
_pieHasSinglePart = false;
|
||||
for (auto k = 0; k < sums.size(); k++) {
|
||||
const auto rawPercentage = sums[k] / totalSum;
|
||||
const auto rawPercentage = totalSum ? (sums[k] / totalSum) : 0.;
|
||||
const auto rounded = 0.01 * std::round(rawPercentage * 100.);
|
||||
roundedPercentagesSum += rounded;
|
||||
const auto diff = rawPercentage - rounded;
|
||||
|
@ -342,13 +342,16 @@ void StackLinearChartView::paintChartOrZoomAnimation(
|
|||
for (auto k = 0; k < c.chartData.lines.size(); k++) {
|
||||
const auto &line = c.chartData.lines[k];
|
||||
const auto isLastLine = (k == lastEnabled);
|
||||
const auto &transitionLine = hasTransitionAnimation
|
||||
? _transition.lines[k]
|
||||
: Transition::TransitionLine();
|
||||
const auto lineAlpha = linesFilter->alpha(line.id);
|
||||
if (isLastLine && (lineAlpha < 1.)) {
|
||||
hasEmptyPoint = true;
|
||||
}
|
||||
if (!lineAlpha) {
|
||||
continue;
|
||||
}
|
||||
const auto &transitionLine = hasTransitionAnimation
|
||||
? _transition.lines[k]
|
||||
: Transition::TransitionLine();
|
||||
const auto &y = line.y;
|
||||
|
||||
auto &chartPath = paths[k];
|
||||
|
@ -357,7 +360,7 @@ void StackLinearChartView::paintChartOrZoomAnimation(
|
|||
? float64(y[i] ? lineAlpha : 0.)
|
||||
: float64(sum ? (y[i] * lineAlpha / sum) : 0.);
|
||||
|
||||
if (!yPercentage && isLastLine) {
|
||||
if (isLastLine && !yPercentage) {
|
||||
hasEmptyPoint = true;
|
||||
}
|
||||
const auto height = yPercentage * c.rect.height();
|
||||
|
@ -425,7 +428,9 @@ void StackLinearChartView::paintChartOrZoomAnimation(
|
|||
}
|
||||
|
||||
if (i == localStart) {
|
||||
const auto bottomLeft = QPointF(c.rect.x(), rect::bottom(c.rect));
|
||||
const auto bottomLeft = QPointF(
|
||||
c.rect.x(),
|
||||
rect::bottom(c.rect));
|
||||
const auto local = (hasTransitionAnimation && !isLastLine)
|
||||
? rotate(
|
||||
_transition.progress * angle
|
||||
|
@ -495,7 +500,9 @@ void StackLinearChartView::paintChartOrZoomAnimation(
|
|||
: rect::right(c.rect));
|
||||
}
|
||||
} else {
|
||||
chartPath.lineTo(rect::right(c.rect), rect::bottom(c.rect));
|
||||
chartPath.lineTo(
|
||||
rect::right(c.rect),
|
||||
rect::bottom(c.rect));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,6 +517,10 @@ void StackLinearChartView::paintChartOrZoomAnimation(
|
|||
p.setClipPath(ovalPath);
|
||||
}
|
||||
|
||||
if (hasEmptyPoint) {
|
||||
p.fillRect(c.rect, st::boxDividerBg);
|
||||
}
|
||||
|
||||
const auto opacity = c.footer ? (1. - _transition.progress) : 1.;
|
||||
for (auto k = int(c.chartData.lines.size() - 1); k >= 0; k--) {
|
||||
if (paths[k].isEmpty()) {
|
||||
|
@ -708,10 +719,13 @@ void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) {
|
|||
}
|
||||
|
||||
const auto rText = side * std::sqrt(1. - percentage);
|
||||
const auto textAngle = (previous + kPieAngleOffset)
|
||||
+ (now - previous) / 2.;
|
||||
const auto textAngle = (now == previous)
|
||||
? 0.
|
||||
: ((previous + kPieAngleOffset) + (now - previous) / 2.);
|
||||
const auto textRadians = textAngle * M_PI / 180.;
|
||||
const auto scale = (minScale) + percentage * (maxScale - minScale);
|
||||
const auto scale = (maxScale == minScale)
|
||||
? 0.
|
||||
: (minScale) + percentage * (maxScale - minScale);
|
||||
const auto text = QString::number(int(percentage * 100)) + u"%"_q;
|
||||
const auto textW = font->width(text);
|
||||
const auto textH = font->height;
|
||||
|
@ -753,7 +767,7 @@ bool StackLinearChartView::PiePartController::set(int id) {
|
|||
void StackLinearChartView::PiePartController::update(int id) {
|
||||
if (id >= 0) {
|
||||
const auto was = _startedAt[id];
|
||||
const auto p = (crl::now() - was) / st::slideWrapDuration;
|
||||
const auto p = (crl::now() - was) / float64(st::slideWrapDuration);
|
||||
const auto progress = ((p > 0) && (p < 1)) ? (1. - p) : 0.;
|
||||
_startedAt[id] = crl::now() - (st::slideWrapDuration * progress);
|
||||
}
|
||||
|
@ -804,10 +818,8 @@ void StackLinearChartView::handleMouseMove(
|
|||
}
|
||||
const auto center = rect.center();
|
||||
const auto theta = std::atan2(center.y() - p.y(), (center.x() - p.x()));
|
||||
const auto angle = [&] {
|
||||
const auto a = theta * (180. / M_PI) + 90.;
|
||||
return (a > 180.) ? (a - 360.) : a;
|
||||
}();
|
||||
const auto rawAngle = theta * (180. / M_PI) + 90.;
|
||||
const auto angle = (rawAngle > 180.) ? (rawAngle - 360.) : rawAngle;
|
||||
for (auto k = 0; k < chartData.lines.size(); k++) {
|
||||
const auto previous = k
|
||||
? _transition.lines[k - 1].angle
|
||||
|
|
Loading…
Add table
Reference in a new issue