Created RpMouseWidget class for easier mouse processing.

This commit is contained in:
23rd 2023-07-06 19:16:02 +03:00 committed by John Preston
parent ec8d604db7
commit dd1b006d8a
2 changed files with 68 additions and 27 deletions

View File

@ -90,6 +90,54 @@ void PaintCaptionsToHorizontalLines(
} // namespace } // 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<State> 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<State> _mouseStateChanged;
};
const QPoint &RpMouseWidget::start() const {
return _start;
}
rpl::producer<RpMouseWidget::State> 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 { class ChartWidget::Footer final : public Ui::AbstractButton {
public: public:
Footer(not_null<Ui::RpWidget*> parent); Footer(not_null<Ui::RpWidget*> parent);
@ -101,8 +149,8 @@ public:
[[nodiscard]] const Limits &fullHeightLimits() const; [[nodiscard]] const Limits &fullHeightLimits() const;
private: private:
not_null<Ui::AbstractButton*> _left; not_null<RpMouseWidget*> _left;
not_null<Ui::AbstractButton*> _right; not_null<RpMouseWidget*> _right;
rpl::event_stream<Limits> _xPercentageLimitsChange; rpl::event_stream<Limits> _xPercentageLimitsChange;
rpl::event_stream<> _userInteractionFinished; rpl::event_stream<> _userInteractionFinished;
@ -110,18 +158,16 @@ private:
Limits _fullHeightLimits; Limits _fullHeightLimits;
struct { struct {
int x = 0; int left = 0;
int leftLimit = 0; int right = 0;
int rightLimit = 0; } _limits;
int diffX = 0;
} _start;
}; };
ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent) ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent)
: Ui::AbstractButton(parent) : Ui::AbstractButton(parent)
, _left(Ui::CreateChild<Ui::AbstractButton>(this)) , _left(Ui::CreateChild<RpMouseWidget>(this))
, _right(Ui::CreateChild<Ui::AbstractButton>(this)) { , _right(Ui::CreateChild<RpMouseWidget>(this)) {
sizeValue( sizeValue(
) | rpl::start_with_next([=](const QSize &s) { ) | rpl::start_with_next([=](const QSize &s) {
_left->resize(st::colorSliderWidth, s.height()); _left->resize(st::colorSliderWidth, s.height());
@ -147,28 +193,23 @@ ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent)
}, _left->lifetime()); }, _left->lifetime());
const auto handleDrag = [&]( const auto handleDrag = [&](
not_null<Ui::AbstractButton*> side, not_null<RpMouseWidget*> side,
Fn<int()> leftLimit, Fn<int()> leftLimit,
Fn<int()> rightLimit) { Fn<int()> rightLimit) {
side->events( side->mouseStateChanged(
) | rpl::filter([=](not_null<QEvent*> e) { ) | rpl::start_with_next([=](const RpMouseWidget::State &state) {
return (e->type() == QEvent::MouseButtonPress) const auto posX = state.point.x();
|| (e->type() == QEvent::MouseButtonRelease) switch (state.mouseState) {
|| ((e->type() == QEvent::MouseMove) && side->isDown());
}) | rpl::start_with_next([=](not_null<QEvent*> e) {
const auto pos = static_cast<QMouseEvent*>(e.get())->pos();
switch (e->type()) {
case QEvent::MouseMove: { case QEvent::MouseMove: {
if (base::IsCtrlPressed()) { if (base::IsCtrlPressed()) {
const auto diff = (pos.x() - _start.x); const auto diff = (posX - side->start().x());
_left->move(_left->x() + diff, side->y()); _left->move(_left->x() + diff, side->y());
_right->move(_right->x() + diff, side->y()); _right->move(_right->x() + diff, side->y());
} else { } else {
_start.diffX = pos.x() - _start.x;
const auto nextX = std::clamp( const auto nextX = std::clamp(
side->x() + (pos.x() - _start.x), side->x() + (posX - side->start().x()),
_start.leftLimit, _limits.left,
_start.rightLimit); _limits.right);
side->move(nextX, side->y()); side->move(nextX, side->y());
} }
_xPercentageLimitsChange.fire({ _xPercentageLimitsChange.fire({
@ -177,9 +218,7 @@ ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent)
}); });
} break; } break;
case QEvent::MouseButtonPress: { case QEvent::MouseButtonPress: {
_start.x = pos.x(); _limits = { .left = leftLimit(), .right = rightLimit() };
_start.leftLimit = leftLimit();
_start.rightLimit = rightLimit();
} break; } break;
case QEvent::MouseButtonRelease: { case QEvent::MouseButtonRelease: {
_userInteractionFinished.fire({}); _userInteractionFinished.fire({});
@ -187,7 +226,7 @@ ChartWidget::Footer::Footer(not_null<Ui::RpWidget*> parent)
.min = _left->x() / float64(width()), .min = _left->x() / float64(width()),
.max = rect::right(_right) / float64(width()), .max = rect::right(_right) / float64(width()),
}); });
_start = {}; _limits = {};
} break; } break;
} }
}, side->lifetime()); }, side->lifetime());

View File

@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Statistic { namespace Statistic {
class RpMouseWidget;
class ChartWidget : public Ui::RpWidget { class ChartWidget : public Ui::RpWidget {
public: public:
ChartWidget(not_null<Ui::RpWidget*> parent); ChartWidget(not_null<Ui::RpWidget*> parent);