mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Added ability to select part of pie chart.
This commit is contained in:
parent
bedefee1d1
commit
42215343cf
3 changed files with 116 additions and 2 deletions
|
@ -47,6 +47,7 @@ statisticsDetailsBottomCaptionStyle: TextStyle(defaultTextStyle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
statisticsPieChartFont: font(20px);
|
statisticsPieChartFont: font(20px);
|
||||||
|
statisticsPieChartPartOffset: 8px;
|
||||||
|
|
||||||
statisticsChartHeaderHeight: 20px;
|
statisticsChartHeaderHeight: 20px;
|
||||||
statisticsHeaderTitleTextStyle: TextStyle(defaultTextStyle) {
|
statisticsHeaderTitleTextStyle: TextStyle(defaultTextStyle) {
|
||||||
|
|
|
@ -437,10 +437,17 @@ void StackLinearChartView::paintZoomed(QPainter &p, const PaintContext &c) {
|
||||||
|
|
||||||
p.setBrush(c.chartData.lines[k].color);
|
p.setBrush(c.chartData.lines[k].color);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
|
const auto textAngle = (previous + kPieAngleOffset)
|
||||||
|
+ (now - previous) / 2.;
|
||||||
|
const auto partOffset = _piePartController.offset(
|
||||||
|
c.chartData.lines[k].id,
|
||||||
|
textAngle);
|
||||||
|
p.translate(partOffset);
|
||||||
p.drawPie(
|
p.drawPie(
|
||||||
rectF,
|
rectF,
|
||||||
-(previous + kPieAngleOffset) * 16,
|
-(previous + kPieAngleOffset) * 16,
|
||||||
-(now - previous) * 16);
|
-(now - previous) * 16);
|
||||||
|
p.translate(-partOffset);
|
||||||
}
|
}
|
||||||
paintPieText(p, c);
|
paintPieText(p, c);
|
||||||
}
|
}
|
||||||
|
@ -482,9 +489,14 @@ void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) {
|
||||||
const auto textRect = QRectF(
|
const auto textRect = QRectF(
|
||||||
textRectCenter - QPointF(textXShift, textYShift),
|
textRectCenter - QPointF(textXShift, textYShift),
|
||||||
textRectCenter + QPointF(textXShift, textYShift));
|
textRectCenter + QPointF(textXShift, textYShift));
|
||||||
|
const auto partOffset = _piePartController.offset(
|
||||||
|
c.chartData.lines[k].id,
|
||||||
|
textAngle);
|
||||||
p.setTransform(
|
p.setTransform(
|
||||||
QTransform()
|
QTransform()
|
||||||
.translate(textRectCenter.x(), textRectCenter.y())
|
.translate(
|
||||||
|
textRectCenter.x() + partOffset.x(),
|
||||||
|
textRectCenter.y() + partOffset.y())
|
||||||
.scale(scale, scale)
|
.scale(scale, scale)
|
||||||
.translate(-textRectCenter.x(), -textRectCenter.y()));
|
.translate(-textRectCenter.x(), -textRectCenter.y()));
|
||||||
p.setOpacity(opacity * alpha(c.chartData.lines[k].id));
|
p.setOpacity(opacity * alpha(c.chartData.lines[k].id));
|
||||||
|
@ -493,6 +505,81 @@ void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) {
|
||||||
p.resetTransform();
|
p.resetTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StackLinearChartView::setUpdateCallback(Fn<void()> callback) {
|
||||||
|
if (callback) {
|
||||||
|
_piePartAnimation.init([=] { callback(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StackLinearChartView::PiePartController::set(int id) {
|
||||||
|
if (_selected != id) {
|
||||||
|
update(_selected);
|
||||||
|
_selected = id;
|
||||||
|
update(_selected);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackLinearChartView::PiePartController::update(int id) {
|
||||||
|
if (id >= 0) {
|
||||||
|
const auto was = _startedAt[id];
|
||||||
|
const auto p = (crl::now() - was) / st::slideWrapDuration;
|
||||||
|
const auto progress = ((p > 0) && (p < 1)) ? (1. - p) : 0.;
|
||||||
|
_startedAt[id] = crl::now() - (st::slideWrapDuration * progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float64 StackLinearChartView::PiePartController::progress(int id) {
|
||||||
|
const auto it = _startedAt.find(id);
|
||||||
|
if (it == end(_startedAt)) {
|
||||||
|
return 0.;
|
||||||
|
}
|
||||||
|
const auto at = it->second;
|
||||||
|
const auto show = (_selected == id);
|
||||||
|
const auto progress = std::clamp(
|
||||||
|
(crl::now() - at) / float64(st::slideWrapDuration),
|
||||||
|
0.,
|
||||||
|
1.);
|
||||||
|
return std::clamp(show ? progress : (1. - progress), 0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF StackLinearChartView::PiePartController::offset(
|
||||||
|
LineId id,
|
||||||
|
float64 angle) {
|
||||||
|
const auto offset = st::statisticsPieChartPartOffset * progress(id);
|
||||||
|
const auto radians = angle * M_PI / 180.;
|
||||||
|
return { std::cos(radians) * offset, std::sin(radians) * offset };
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackLinearChartView::handleMouseMove(
|
||||||
|
const Data::StatisticalChart &chartData,
|
||||||
|
const QPoint ¢er,
|
||||||
|
const QPoint &p) {
|
||||||
|
if (_transitionProgress < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}();
|
||||||
|
for (auto k = 0; k < chartData.lines.size(); k++) {
|
||||||
|
const auto previous = k
|
||||||
|
? _cachedTransition.lines[k - 1].angle
|
||||||
|
: -180;
|
||||||
|
const auto now = _cachedTransition.lines[k].angle;
|
||||||
|
if (angle > previous && angle <= now) {
|
||||||
|
if (_piePartController.set(chartData.lines[k].id)) {
|
||||||
|
if (!_piePartAnimation.animating()) {
|
||||||
|
_piePartAnimation.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StackLinearChartView::paintSelectedXIndex(
|
void StackLinearChartView::paintSelectedXIndex(
|
||||||
QPainter &p,
|
QPainter &p,
|
||||||
const Data::StatisticalChart &chartData,
|
const Data::StatisticalChart &chartData,
|
||||||
|
@ -548,7 +635,9 @@ int StackLinearChartView::findXIndexByPosition(
|
||||||
const Limits &xPercentageLimits,
|
const Limits &xPercentageLimits,
|
||||||
const QRect &rect,
|
const QRect &rect,
|
||||||
float64 x) {
|
float64 x) {
|
||||||
if (x < rect.x()) {
|
if (_transitionProgress == 1.) {
|
||||||
|
return -1;
|
||||||
|
} else if (x < rect.x()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (x > (rect.x() + rect.width())) {
|
} else if (x > (rect.x() + rect.width())) {
|
||||||
return chartData.xPercentage.size() - 1;
|
return chartData.xPercentage.size() - 1;
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "statistics/segment_tree.h"
|
#include "statistics/segment_tree.h"
|
||||||
#include "statistics/statistics_common.h"
|
#include "statistics/statistics_common.h"
|
||||||
#include "statistics/view/abstract_chart_view.h"
|
#include "statistics/view/abstract_chart_view.h"
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/effects/animation_value.h"
|
#include "ui/effects/animation_value.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -61,6 +62,12 @@ public:
|
||||||
void tick(crl::time now) override;
|
void tick(crl::time now) override;
|
||||||
void update(float64 dt) override;
|
void update(float64 dt) override;
|
||||||
|
|
||||||
|
void setUpdateCallback(Fn<void()> callback);
|
||||||
|
void handleMouseMove(
|
||||||
|
const Data::StatisticalChart &chartData,
|
||||||
|
const QPoint ¢er,
|
||||||
|
const QPoint &p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PaintContext final {
|
struct PaintContext final {
|
||||||
const Data::StatisticalChart &chartData;
|
const Data::StatisticalChart &chartData;
|
||||||
|
@ -115,6 +122,23 @@ private:
|
||||||
|
|
||||||
std::vector<bool> _skipPoints;
|
std::vector<bool> _skipPoints;
|
||||||
|
|
||||||
|
class PiePartController final {
|
||||||
|
public:
|
||||||
|
using LineId = int;
|
||||||
|
bool set(LineId id);
|
||||||
|
[[nodiscard]] float64 progress(LineId id);
|
||||||
|
[[nodiscard]] QPointF offset(LineId id, float64 angle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update(LineId id);
|
||||||
|
|
||||||
|
base::flat_map<LineId, crl::time> _startedAt;
|
||||||
|
LineId _selected = -1;
|
||||||
|
|
||||||
|
};
|
||||||
|
PiePartController _piePartController;
|
||||||
|
Ui::Animations::Basic _piePartAnimation;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Statistic
|
} // namespace Statistic
|
||||||
|
|
Loading…
Add table
Reference in a new issue