Added details popup to selected part of pie chart.
This commit is contained in:
parent
42215343cf
commit
83753343cb
|
@ -32,6 +32,57 @@ namespace {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void PaintDetails(
|
||||||
|
QPainter &p,
|
||||||
|
const Data::StatisticalChart::Line &line,
|
||||||
|
int absoluteValue,
|
||||||
|
const QRect &rect) {
|
||||||
|
auto name = Ui::Text::String(
|
||||||
|
st::statisticsDetailsPopupStyle,
|
||||||
|
line.name);
|
||||||
|
auto value = Ui::Text::String(
|
||||||
|
st::statisticsDetailsPopupStyle,
|
||||||
|
QString("%L1").arg(absoluteValue));
|
||||||
|
const auto nameWidth = name.maxWidth();
|
||||||
|
const auto valueWidth = value.maxWidth();
|
||||||
|
|
||||||
|
const auto width = valueWidth
|
||||||
|
+ rect::m::sum::h(st::statisticsDetailsPopupMargins)
|
||||||
|
+ rect::m::sum::h(st::statisticsDetailsPopupPadding)
|
||||||
|
+ st::statisticsDetailsPopupPadding.left() // Between strings.
|
||||||
|
+ nameWidth;
|
||||||
|
|
||||||
|
const auto height = st::statisticsDetailsPopupStyle.font->height
|
||||||
|
+ rect::m::sum::v(st::statisticsDetailsPopupMargins)
|
||||||
|
+ rect::m::sum::v(st::statisticsDetailsPopupPadding);
|
||||||
|
|
||||||
|
const auto fullRect = QRect(
|
||||||
|
rect.x() + rect.width() - width,
|
||||||
|
rect.y(),
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
|
||||||
|
const auto innerRect = fullRect - st::statisticsDetailsPopupPadding;
|
||||||
|
const auto textRect = innerRect - st::statisticsDetailsPopupMargins;
|
||||||
|
|
||||||
|
Ui::Shadow::paint(p, innerRect, rect.width(), st::boxRoundShadow);
|
||||||
|
Ui::FillRoundRect(p, innerRect, st::boxBg, Ui::BoxCorners);
|
||||||
|
|
||||||
|
const auto lineY = textRect.y();
|
||||||
|
const auto valueContext = Ui::Text::PaintContext{
|
||||||
|
.position = QPoint(rect::right(textRect) - valueWidth, lineY),
|
||||||
|
};
|
||||||
|
const auto nameContext = Ui::Text::PaintContext{
|
||||||
|
.position = QPoint(textRect.x(), lineY),
|
||||||
|
.outerWidth = textRect.width() - valueWidth,
|
||||||
|
.availableWidth = textRect.width(),
|
||||||
|
};
|
||||||
|
p.setPen(st::boxTextFg);
|
||||||
|
name.draw(p, nameContext);
|
||||||
|
p.setPen(line.color);
|
||||||
|
value.draw(p, valueContext);
|
||||||
|
}
|
||||||
|
|
||||||
PointDetailsWidget::PointDetailsWidget(
|
PointDetailsWidget::PointDetailsWidget(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
const Data::StatisticalChart &chartData,
|
const Data::StatisticalChart &chartData,
|
||||||
|
|
|
@ -12,6 +12,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Statistic {
|
namespace Statistic {
|
||||||
|
|
||||||
|
void PaintDetails(
|
||||||
|
QPainter &p,
|
||||||
|
const Data::StatisticalChart::Line &line,
|
||||||
|
int absoluteValue,
|
||||||
|
const QRect &rect);
|
||||||
|
|
||||||
class PointDetailsWidget : public Ui::RippleButton {
|
class PointDetailsWidget : public Ui::RippleButton {
|
||||||
public:
|
public:
|
||||||
PointDetailsWidget(
|
PointDetailsWidget(
|
||||||
|
|
|
@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "statistics/view/stack_linear_chart_view.h"
|
#include "statistics/view/stack_linear_chart_view.h"
|
||||||
|
|
||||||
#include "ui/effects/animation_value_f.h"
|
|
||||||
#include "data/data_statistics.h"
|
#include "data/data_statistics.h"
|
||||||
|
#include "statistics/point_details_widget.h"
|
||||||
|
#include "ui/effects/animation_value_f.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "ui/rect.h"
|
#include "ui/rect.h"
|
||||||
#include "styles/style_statistics.h"
|
#include "styles/style_statistics.h"
|
||||||
|
@ -429,27 +430,43 @@ void StackLinearChartView::paintZoomed(QPainter &p, const PaintContext &c) {
|
||||||
center + QPointF(side, side));
|
center + QPointF(side, side));
|
||||||
|
|
||||||
auto hq = PainterHighQualityEnabler(p);
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
auto selectedLineIndex = -1;
|
||||||
for (auto k = 0; k < c.chartData.lines.size(); k++) {
|
for (auto k = 0; k < c.chartData.lines.size(); k++) {
|
||||||
const auto previous = k
|
const auto previous = k
|
||||||
? _cachedTransition.lines[k - 1].angle
|
? _cachedTransition.lines[k - 1].angle
|
||||||
: -180;
|
: -180;
|
||||||
const auto now = _cachedTransition.lines[k].angle;
|
const auto now = _cachedTransition.lines[k].angle;
|
||||||
|
|
||||||
p.setBrush(c.chartData.lines[k].color);
|
const auto &line = c.chartData.lines[k];
|
||||||
|
p.setBrush(line.color);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
const auto textAngle = (previous + kPieAngleOffset)
|
const auto textAngle = (previous + kPieAngleOffset)
|
||||||
+ (now - previous) / 2.;
|
+ (now - previous) / 2.;
|
||||||
const auto partOffset = _piePartController.offset(
|
const auto partOffset = _piePartController.offset(line.id, textAngle);
|
||||||
c.chartData.lines[k].id,
|
|
||||||
textAngle);
|
|
||||||
p.translate(partOffset);
|
p.translate(partOffset);
|
||||||
p.drawPie(
|
p.drawPie(
|
||||||
rectF,
|
rectF,
|
||||||
-(previous + kPieAngleOffset) * 16,
|
-(previous + kPieAngleOffset) * 16,
|
||||||
-(now - previous) * 16);
|
-(now - previous) * 16);
|
||||||
p.translate(-partOffset);
|
p.translate(-partOffset);
|
||||||
|
if (_piePartController.selected() == line.id) {
|
||||||
|
selectedLineIndex = k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
paintPieText(p, c);
|
paintPieText(p, c);
|
||||||
|
|
||||||
|
if (selectedLineIndex >= 0) {
|
||||||
|
const auto &[localStart, localEnd] = _lastPaintedXIndices;
|
||||||
|
const auto &line = c.chartData.lines[selectedLineIndex];
|
||||||
|
auto sum = 0;
|
||||||
|
for (auto i = localStart; i <= localEnd; i++) {
|
||||||
|
sum += line.y[i];
|
||||||
|
}
|
||||||
|
sum *= alpha(line.id);
|
||||||
|
if (sum > 0) {
|
||||||
|
PaintDetails(p, line, sum, c.rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) {
|
void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) {
|
||||||
|
@ -552,6 +569,10 @@ QPointF StackLinearChartView::PiePartController::offset(
|
||||||
return { std::cos(radians) * offset, std::sin(radians) * offset };
|
return { std::cos(radians) * offset, std::sin(radians) * offset };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto StackLinearChartView::PiePartController::selected() const -> LineId {
|
||||||
|
return _selected;
|
||||||
|
}
|
||||||
|
|
||||||
void StackLinearChartView::handleMouseMove(
|
void StackLinearChartView::handleMouseMove(
|
||||||
const Data::StatisticalChart &chartData,
|
const Data::StatisticalChart &chartData,
|
||||||
const QPoint ¢er,
|
const QPoint ¢er,
|
||||||
|
@ -570,7 +591,10 @@ void StackLinearChartView::handleMouseMove(
|
||||||
: -180;
|
: -180;
|
||||||
const auto now = _cachedTransition.lines[k].angle;
|
const auto now = _cachedTransition.lines[k].angle;
|
||||||
if (angle > previous && angle <= now) {
|
if (angle > previous && angle <= now) {
|
||||||
if (_piePartController.set(chartData.lines[k].id)) {
|
const auto id = p.isNull()
|
||||||
|
? -1
|
||||||
|
: chartData.lines[k].id;
|
||||||
|
if (_piePartController.set(id)) {
|
||||||
if (!_piePartAnimation.animating()) {
|
if (!_piePartAnimation.animating()) {
|
||||||
_piePartAnimation.start();
|
_piePartAnimation.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,7 @@ private:
|
||||||
bool set(LineId id);
|
bool set(LineId id);
|
||||||
[[nodiscard]] float64 progress(LineId id);
|
[[nodiscard]] float64 progress(LineId id);
|
||||||
[[nodiscard]] QPointF offset(LineId id, float64 angle);
|
[[nodiscard]] QPointF offset(LineId id, float64 angle);
|
||||||
|
[[nodiscard]] LineId selected() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update(LineId id);
|
void update(LineId id);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user