From ec8d604db7520fca215b5b6ffc2a808289bd4f49 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 6 Jul 2023 14:09:16 +0300 Subject: [PATCH] Added initial widget implementation of point details in charts. --- Telegram/CMakeLists.txt | 2 + .../statistics/point_details_widget.cpp | 97 +++++++++++++++++++ .../statistics/point_details_widget.h | 47 +++++++++ .../SourceFiles/statistics/statistics.style | 20 ++++ Telegram/cmake/td_ui.cmake | 1 + 5 files changed, 167 insertions(+) create mode 100644 Telegram/SourceFiles/statistics/point_details_widget.cpp create mode 100644 Telegram/SourceFiles/statistics/point_details_widget.h create mode 100644 Telegram/SourceFiles/statistics/statistics.style diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 97ce9013f..00d68e1a3 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -1288,6 +1288,8 @@ PRIVATE statistics/chart_widget.h statistics/linear_chart_view.cpp statistics/linear_chart_view.h + statistics/point_details_widget.cpp + statistics/point_details_widget.h statistics/segment_tree.cpp statistics/segment_tree.h statistics/statistics_box.cpp diff --git a/Telegram/SourceFiles/statistics/point_details_widget.cpp b/Telegram/SourceFiles/statistics/point_details_widget.cpp new file mode 100644 index 000000000..ece3b051d --- /dev/null +++ b/Telegram/SourceFiles/statistics/point_details_widget.cpp @@ -0,0 +1,97 @@ +/* +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/point_details_widget.h" + +#include "ui/cached_round_corners.h" +#include "ui/rect.h" +#include "ui/widgets/shadow.h" +#include "styles/style_layers.h" +#include "styles/style_statistics.h" + +namespace Statistic { + +PointDetailsWidget::PointDetailsWidget( + not_null parent, + const Data::StatisticalChart &chartData) +: Ui::RpWidget(parent) +, _chartData(chartData) +, _textStyle(st::statisticsDetailsPopupStyle) +, _headerStyle(st::semiboldTextStyle) { + sizeValue( + ) | rpl::start_with_next([=](const QSize &s) { + const auto fullRect = s.isNull() + ? Rect(Size(st::statisticsDetailsPopupWidth)) + : Rect(s); + _innerRect = fullRect - st::statisticsDetailsPopupPadding; + _textRect = _innerRect - st::statisticsDetailsPopupMargins; + }, lifetime()); + + resize( + st::statisticsDetailsPopupWidth, + lineYAt(chartData.lines.size()) + + st::statisticsDetailsPopupMargins.bottom()); +} + +void PointDetailsWidget::setXIndex(int xIndex) { + _header.setText(_headerStyle, _chartData.getDayString(xIndex)); + + _lines.clear(); + _lines.reserve(_chartData.lines.size()); + for (const auto &dataLine : _chartData.lines) { + auto textLine = Line(); + textLine.name.setText(_textStyle, dataLine.name); + textLine.value.setText( + _textStyle, + QString::number(dataLine.y[xIndex])); + textLine.valueColor = QColor(dataLine.color); + _lines.push_back(std::move(textLine)); + } +} + +int PointDetailsWidget::lineYAt(int i) const { + return _textRect.y() + + _headerStyle.font->height + + st::statisticsDetailsPopupMargins.bottom() + + (_textStyle.font->height * i) + + (st::statisticsDetailsPopupMidLineSpace * i); +} + +void PointDetailsWidget::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + + const auto fullRect = rect(); + + Ui::Shadow::paint(p, _innerRect, width(), st::boxRoundShadow); + Ui::FillRoundRect(p, _innerRect, st::boxBg, Ui::BoxCorners); + + p.setPen(st::boxTextFg); + const auto headerContext = Ui::Text::PaintContext{ + .position = _textRect.topLeft(), + .availableWidth = _textRect.width(), + }; + _header.draw(p, headerContext); + for (auto i = 0; i < _lines.size(); i++) { + const auto &line = _lines[i]; + const auto lineY = lineYAt(i); + const auto valueWidth = line.value.maxWidth(); + 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); + line.name.draw(p, nameContext); + p.setPen(line.valueColor); + line.value.draw(p, valueContext); + } +} + +} // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/point_details_widget.h b/Telegram/SourceFiles/statistics/point_details_widget.h new file mode 100644 index 000000000..5d3333aab --- /dev/null +++ b/Telegram/SourceFiles/statistics/point_details_widget.h @@ -0,0 +1,47 @@ +/* +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 + +#include "data/data_statistics.h" +#include "ui/rp_widget.h" + +namespace Statistic { + +class PointDetailsWidget : public Ui::RpWidget { +public: + PointDetailsWidget( + not_null parent, + const Data::StatisticalChart &chartData); + + void setXIndex(int xIndex); + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + const Data::StatisticalChart &_chartData; + const style::TextStyle &_textStyle; + const style::TextStyle &_headerStyle; + Ui::Text::String _header; + + [[nodiscard]] int lineYAt(int i) const; + + struct Line final { + Ui::Text::String name; + Ui::Text::String value; + QColor valueColor; + }; + + QRect _innerRect; + QRect _textRect; + + std::vector _lines; + +}; + +} // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/statistics.style b/Telegram/SourceFiles/statistics/statistics.style new file mode 100644 index 000000000..dbc35f5d4 --- /dev/null +++ b/Telegram/SourceFiles/statistics/statistics.style @@ -0,0 +1,20 @@ +/* +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 +*/ +using "ui/basic.style"; + +using "window/window.style"; +using "ui/widgets/widgets.style"; + +statisticsDetailsPopupWidth: 135px; +statisticsDetailsPopupMargins: margins(8px, 8px, 8px, 8px); +statisticsDetailsPopupPadding: margins(6px, 6px, 6px, 6px); +statisticsDetailsPopupMidLineSpace: 8px; + +statisticsDetailsPopupStyle: TextStyle(defaultTextStyle) { + font: font(11px); +} diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 7e2955ac1..87436fffa 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -34,6 +34,7 @@ set(style_files overview/overview.style window/window.style editor/editor.style + statistics/statistics.style ) set(dependent_style_files