diff --git a/ui/widgets/checkbox.cpp b/ui/widgets/checkbox.cpp index 9469dc0..6bfe533 100644 --- a/ui/widgets/checkbox.cpp +++ b/ui/widgets/checkbox.cpp @@ -486,6 +486,9 @@ Checkbox::Checkbox( std::move(value), _checkboxRichOptions); resizeToText(); + if (_text.hasLinks()) { + setMouseTracking(true); + } update(); } }, lifetime()); @@ -689,6 +692,59 @@ void Checkbox::paintEvent(QPaintEvent *e) { } } +void Checkbox::mousePressEvent(QMouseEvent *e) { + RippleButton::mousePressEvent(e); + ClickHandler::pressed(); +} + +void Checkbox::mouseMoveEvent(QMouseEvent *e) { + RippleButton::mouseMoveEvent(e); + const auto state = getTextState(e->pos()); + if (state.link != ClickHandler::getActive()) { + ClickHandler::setActive(state.link, this); + update(); + } +} + +void Checkbox::mouseReleaseEvent(QMouseEvent *e) { + if (auto activated = _activatingHandler = ClickHandler::unpressed()) { + const auto button = e->button(); + crl::on_main(this, [=] { + const auto guard = window(); + ActivateClickHandler(guard, activated, button); + }); + } + RippleButton::mouseReleaseEvent(e); + _activatingHandler = nullptr; +} + +void Checkbox::leaveEventHook(QEvent *e) { + RippleButton::leaveEventHook(e); + ClickHandler::clearActive(this); +} + +Text::StateResult Checkbox::getTextState(const QPoint &m) const { + if (!(_checkAlignment & Qt::AlignLeft)) { + return {}; + } + const auto check = checkRect(); + const auto textSkip = _st.checkPosition.x() + + check.width() + + _st.textPosition.x(); + const auto availableTextWidth = std::max(width() - textSkip, 1); + const auto textTop = _st.margin.top() + _st.textPosition.y(); + return !_allowTextLines + ? _text.getStateElided( + m - QPoint(textSkip, textTop), + availableTextWidth, + {}) + : _text.getStateElidedLeft( + m - QPoint(textSkip, textTop), + availableTextWidth, + width(), + {}); +} + QPixmap Checkbox::grabCheckCache() const { auto checkSize = _check->getSize(); auto image = QImage( @@ -724,7 +780,9 @@ void Checkbox::onStateChanged(State was, StateChangeSource source) { } void Checkbox::handlePress() { - setChecked(!checked()); + if (!_activatingHandler) { + setChecked(!checked()); + } } int Checkbox::resizeGetHeight(int newWidth) { diff --git a/ui/widgets/checkbox.h b/ui/widgets/checkbox.h index 9ffe452..bc06065 100644 --- a/ui/widgets/checkbox.h +++ b/ui/widgets/checkbox.h @@ -132,7 +132,7 @@ private: }; -class Checkbox : public RippleButton { +class Checkbox : public RippleButton, public ClickHandlerHost { public: Checkbox( QWidget *parent, @@ -210,6 +210,11 @@ public: protected: void paintEvent(QPaintEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void leaveEventHook(QEvent *e) override; + void onStateChanged(State was, StateChangeSource source) override; int resizeGetHeight(int newWidth) override; @@ -222,10 +227,12 @@ private: void resizeToText(); QPixmap grabCheckCache() const; int countTextMinWidth() const; + Text::StateResult getTextState(const QPoint &m) const; const style::Checkbox &_st; std::unique_ptr _check; rpl::event_stream _checkedChanges; + ClickHandlerPtr _activatingHandler; QPixmap _checkCache; style::align _checkAlignment = style::al_left;