From dd1b006d8af36b6a6d5f0ed63321636d610af829 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Thu, 6 Jul 2023 19:16:02 +0300 Subject: [PATCH] Created RpMouseWidget class for easier mouse processing. --- .../SourceFiles/statistics/chart_widget.cpp | 93 +++++++++++++------ .../SourceFiles/statistics/chart_widget.h | 2 + 2 files changed, 68 insertions(+), 27 deletions(-) diff --git a/Telegram/SourceFiles/statistics/chart_widget.cpp b/Telegram/SourceFiles/statistics/chart_widget.cpp index 5b79b529c..795165fe5 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.cpp +++ b/Telegram/SourceFiles/statistics/chart_widget.cpp @@ -90,6 +90,54 @@ void PaintCaptionsToHorizontalLines( } // namespace +class RpMouseWidget final : public Ui::AbstractButton { +public: + using Ui::AbstractButton::AbstractButton; + + struct State { + QPoint point; + QEvent::Type mouseState; + }; + + [[nodiscard]] const QPoint &start() const; + [[nodiscard]] rpl::producer mouseStateChanged() const; + +protected: + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + +private: + QPoint _start = QPoint(-1, -1); + + rpl::event_stream _mouseStateChanged; + +}; + +const QPoint &RpMouseWidget::start() const { + return _start; +} + +rpl::producer RpMouseWidget::mouseStateChanged() const { + return _mouseStateChanged.events(); +} + +void RpMouseWidget::mousePressEvent(QMouseEvent *e) { + _start = e->pos(); + _mouseStateChanged.fire({ e->pos(), QEvent::MouseButtonPress }); +} + +void RpMouseWidget::mouseMoveEvent(QMouseEvent *e) { + if (_start.x() >= 0 || _start.y() >= 0) { + _mouseStateChanged.fire({ e->pos(), QEvent::MouseMove }); + } +} + +void RpMouseWidget::mouseReleaseEvent(QMouseEvent *e) { + _start = { -1, -1 }; + _mouseStateChanged.fire({ e->pos(), QEvent::MouseButtonRelease }); +} + class ChartWidget::Footer final : public Ui::AbstractButton { public: Footer(not_null parent); @@ -101,8 +149,8 @@ public: [[nodiscard]] const Limits &fullHeightLimits() const; private: - not_null _left; - not_null _right; + not_null _left; + not_null _right; rpl::event_stream _xPercentageLimitsChange; rpl::event_stream<> _userInteractionFinished; @@ -110,18 +158,16 @@ private: Limits _fullHeightLimits; struct { - int x = 0; - int leftLimit = 0; - int rightLimit = 0; - int diffX = 0; - } _start; + int left = 0; + int right = 0; + } _limits; }; ChartWidget::Footer::Footer(not_null parent) : Ui::AbstractButton(parent) -, _left(Ui::CreateChild(this)) -, _right(Ui::CreateChild(this)) { +, _left(Ui::CreateChild(this)) +, _right(Ui::CreateChild(this)) { sizeValue( ) | rpl::start_with_next([=](const QSize &s) { _left->resize(st::colorSliderWidth, s.height()); @@ -147,28 +193,23 @@ ChartWidget::Footer::Footer(not_null parent) }, _left->lifetime()); const auto handleDrag = [&]( - not_null side, + not_null side, Fn leftLimit, Fn rightLimit) { - side->events( - ) | rpl::filter([=](not_null e) { - return (e->type() == QEvent::MouseButtonPress) - || (e->type() == QEvent::MouseButtonRelease) - || ((e->type() == QEvent::MouseMove) && side->isDown()); - }) | rpl::start_with_next([=](not_null e) { - const auto pos = static_cast(e.get())->pos(); - switch (e->type()) { + side->mouseStateChanged( + ) | rpl::start_with_next([=](const RpMouseWidget::State &state) { + const auto posX = state.point.x(); + switch (state.mouseState) { case QEvent::MouseMove: { if (base::IsCtrlPressed()) { - const auto diff = (pos.x() - _start.x); + const auto diff = (posX - side->start().x()); _left->move(_left->x() + diff, side->y()); _right->move(_right->x() + diff, side->y()); } else { - _start.diffX = pos.x() - _start.x; const auto nextX = std::clamp( - side->x() + (pos.x() - _start.x), - _start.leftLimit, - _start.rightLimit); + side->x() + (posX - side->start().x()), + _limits.left, + _limits.right); side->move(nextX, side->y()); } _xPercentageLimitsChange.fire({ @@ -177,9 +218,7 @@ ChartWidget::Footer::Footer(not_null parent) }); } break; case QEvent::MouseButtonPress: { - _start.x = pos.x(); - _start.leftLimit = leftLimit(); - _start.rightLimit = rightLimit(); + _limits = { .left = leftLimit(), .right = rightLimit() }; } break; case QEvent::MouseButtonRelease: { _userInteractionFinished.fire({}); @@ -187,7 +226,7 @@ ChartWidget::Footer::Footer(not_null parent) .min = _left->x() / float64(width()), .max = rect::right(_right) / float64(width()), }); - _start = {}; + _limits = {}; } break; } }, side->lifetime()); diff --git a/Telegram/SourceFiles/statistics/chart_widget.h b/Telegram/SourceFiles/statistics/chart_widget.h index afa5227b8..03556aee6 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.h +++ b/Telegram/SourceFiles/statistics/chart_widget.h @@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Statistic { +class RpMouseWidget; + class ChartWidget : public Ui::RpWidget { public: ChartWidget(not_null parent);