From bdd35a6e2b96fdedd3114b48115dcb8e609c219a Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Tue, 26 Sep 2023 23:09:44 +0300 Subject: [PATCH] Added ability to handle mouse move to chart views. --- .../SourceFiles/statistics/chart_widget.cpp | 31 +++++++++++++++++++ .../statistics/view/abstract_chart_view.h | 18 +++++++++++ .../view/stack_linear_chart_view.cpp | 13 +++----- .../statistics/view/stack_linear_chart_view.h | 5 ++- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/Telegram/SourceFiles/statistics/chart_widget.cpp b/Telegram/SourceFiles/statistics/chart_widget.cpp index 261892e98..83119a646 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.cpp +++ b/Telegram/SourceFiles/statistics/chart_widget.cpp @@ -1233,6 +1233,31 @@ void ChartWidget::processLocalZoom(int xIndex) { }, header->lifetime()); header->setRightInfo(_chartData.getDayString(xIndex)); + const auto enableMouse = [=](bool value) { + setAttribute(Qt::WA_TransparentForMouseEvents, !value); + }; + + const auto mouseTrackingLifetime = std::make_shared(); + _chartView->setUpdateCallback([=] { _chartArea->update(); }); + const auto createMouseTracking = [=] { + _chartArea->setMouseTracking(true); + *mouseTrackingLifetime = _chartArea->events( + ) | rpl::filter([](not_null event) { + return (event->type() == QEvent::MouseMove) + || (event->type() == QEvent::Leave); + }) | rpl::start_with_next([=](not_null event) { + auto pos = QPoint(); + if (event->type() == QEvent::MouseMove) { + const auto e = static_cast(event.get()); + pos = e->pos(); + } + _chartView->handleMouseMove(_chartData, _chartArea->rect(), pos); + }); + mouseTrackingLifetime->add([=] { + _chartArea->setMouseTracking(false); + }); + }; + const auto zoomOutButton = Ui::CreateChild( header, tr::lng_stats_zoom_out(), @@ -1259,8 +1284,11 @@ void ChartWidget::processLocalZoom(int xIndex) { if (lifetime) { lifetime->destroy(); } + mouseTrackingLifetime->destroy(); + enableMouse(true); } }, 1., 0., kFooterZoomDuration, anim::easeOutCirc); + enableMouse(false); Ui::Animations::HideWidgets({ header }); }); @@ -1270,6 +1298,7 @@ void ChartWidget::processLocalZoom(int xIndex) { zoomOutButton->moveToLeft(0, 0); const auto finish = [=](const Limits &zoomLimitIndices) { + createMouseTracking(); _footer->xPercentageLimitsChange( ) | rpl::start_with_next([=](const Limits &l) { const auto result = FindStackXIndicesFromRawXPercentages( @@ -1302,8 +1331,10 @@ void ChartWidget::processLocalZoom(int xIndex) { lifetime->destroy(); } finish(zoom.limitIndices); + enableMouse(true); } }, 0., 1., kFooterZoomDuration, anim::easeOutCirc); + enableMouse(false); } } diff --git a/Telegram/SourceFiles/statistics/view/abstract_chart_view.h b/Telegram/SourceFiles/statistics/view/abstract_chart_view.h index b54c9d4d7..0196c91b1 100644 --- a/Telegram/SourceFiles/statistics/view/abstract_chart_view.h +++ b/Telegram/SourceFiles/statistics/view/abstract_chart_view.h @@ -84,6 +84,24 @@ public: return {}; } + virtual void handleMouseMove( + const Data::StatisticalChart &chartData, + const QRect &rect, + const QPoint &p) { + } + + void setUpdateCallback(Fn callback) { + _updateCallback = std::move(callback); + } + void update() { + if (_updateCallback) { + _updateCallback(); + } + } + +private: + Fn _updateCallback; + }; } // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp index 337c8fb36..67875b2e0 100644 --- a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp @@ -87,7 +87,9 @@ inline float64 InterpolationRatio(float64 from, float64 to, float64 result) { } // namespace -StackLinearChartView::StackLinearChartView() = default; +StackLinearChartView::StackLinearChartView() { + _piePartAnimation.init([=] { AbstractChartView::update(); }); +} StackLinearChartView::~StackLinearChartView() = default; @@ -732,12 +734,6 @@ void StackLinearChartView::paintPieText(QPainter &p, const PaintContext &c) { p.resetTransform(); } -void StackLinearChartView::setUpdateCallback(Fn callback) { - if (callback) { - _piePartAnimation.init([=] { callback(); }); - } -} - bool StackLinearChartView::PiePartController::set(int id) { if (_selected != id) { update(_selected); @@ -795,11 +791,12 @@ bool StackLinearChartView::PiePartController::isFinished() const { void StackLinearChartView::handleMouseMove( const Data::StatisticalChart &chartData, - const QPoint ¢er, + const QRect &rect, const QPoint &p) { if (_transition.progress < 1) { return; } + 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.; diff --git a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.h b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.h index 93ae9deae..bc8e0b9ba 100644 --- a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.h +++ b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.h @@ -54,11 +54,10 @@ public: LocalZoomResult maybeLocalZoom(const LocalZoomArgs &args) override final; - void setUpdateCallback(Fn callback); void handleMouseMove( const Data::StatisticalChart &chartData, - const QPoint ¢er, - const QPoint &p); + const QRect &rect, + const QPoint &p) override; private: enum class TransitionStep {