From 0402b4f5f47dd12895d6407740f93c04613d79a3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 9 Jul 2017 18:06:27 +0300 Subject: [PATCH] Add X / V vector icon to checkbox Toggle view. Also use them in the admin rights / restrictions boxes. --- Telegram/SourceFiles/boxes/boxes.style | 13 ++ .../boxes/edit_participant_box.cpp | 14 +- .../history/history_admin_log_filter.cpp | 7 +- .../media/player/media_player_button.cpp | 29 +--- Telegram/SourceFiles/ui/abstract_button.h | 2 +- Telegram/SourceFiles/ui/animation.h | 31 ++++ Telegram/SourceFiles/ui/text/text_entity.cpp | 2 +- Telegram/SourceFiles/ui/widgets/buttons.cpp | 2 +- Telegram/SourceFiles/ui/widgets/buttons.h | 7 +- Telegram/SourceFiles/ui/widgets/checkbox.cpp | 163 ++++++++++++++++-- Telegram/SourceFiles/ui/widgets/checkbox.h | 23 ++- Telegram/SourceFiles/ui/widgets/widgets.style | 21 ++- 12 files changed, 250 insertions(+), 64 deletions(-) diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index b4b8eb4c1..025bd2d0b 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -645,3 +645,16 @@ adminLogFilterSkip: 32px; adminLogFilterUserCheckbox: Checkbox(defaultBoxCheckbox) { margin: margins(8px, 6px, 8px, 6px); } + +rightsCheckbox: Checkbox(defaultBoxCheckbox) { + rippleBg: attentionButtonBgOver; +} +rightsToggle: Toggle(defaultToggle) { + toggledFg: windowBgActive; + untoggledFg: attentionButtonFg; + xsize: 8px; + vsize: 5px; + vshift: 1px; + stroke: 2px; + duration: 120; +} diff --git a/Telegram/SourceFiles/boxes/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/edit_participant_box.cpp index 3ec84a363..3d0b57d22 100644 --- a/Telegram/SourceFiles/boxes/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_participant_box.cpp @@ -189,16 +189,16 @@ void EditAdminBox::prepare() { auto prepareRights = (_oldRights.c_channelAdminRights().vflags.v ? _oldRights : DefaultRights(channel())); auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) { - if (!channel()->amCreator()) { - if (!(channel()->adminRights().vflags.v & flags)) { - return; // Don't add options that we don't have ourselves. - } - } auto checked = (prepareRights.c_channelAdminRights().vflags.v & flags) != 0; - auto control = addControl(object_ptr(this, text, checked, st::defaultBoxCheckbox)); + auto control = addControl(object_ptr(this, text, checked, st::rightsCheckbox, st::rightsToggle)); subscribe(control->checkedChanged, [this, control](bool checked) { InvokeQueued(this, [this, control] { applyDependencies(control); }); }); + if (!channel()->amCreator()) { + if (!(channel()->adminRights().vflags.v & flags)) { + control->setDisabled(true); // Grey out options that we don't have ourselves. + } + } _checkboxes.emplace(flags, control); }; if (channel()->isMegagroup()) { @@ -297,7 +297,7 @@ void EditRestrictedBox::prepare() { auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) { auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0; - auto control = addControl(object_ptr(this, text, checked, st::defaultBoxCheckbox)); + auto control = addControl(object_ptr(this, text, checked, st::rightsCheckbox, st::rightsToggle)); subscribe(control->checkedChanged, [this, control](bool checked) { InvokeQueued(this, [this, control] { applyDependencies(control); }); }); diff --git a/Telegram/SourceFiles/history/history_admin_log_filter.cpp b/Telegram/SourceFiles/history/history_admin_log_filter.cpp index 07872e941..3a4def41d 100644 --- a/Telegram/SourceFiles/history/history_admin_log_filter.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_filter.cpp @@ -134,15 +134,12 @@ int UserCheckbox::resizeGetHeight(int newWidth) { } QImage UserCheckbox::prepareRippleMask() const { - return Ui::RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); + return _check->prepareRippleMask(); } QPoint UserCheckbox::prepareRippleStartPosition() const { auto position = mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition - QPoint(0, _checkRect.y() - st::defaultBoxCheckbox.margin.top()); - if (QRect(0, 0, _st.rippleAreaSize, _st.rippleAreaSize).contains(position)) { - return position; - } - return disabledRippleStartPosition(); + return _check->checkRippleStartPosition(position) ? position : DisabledRippleStartPosition(); } } // namespace diff --git a/Telegram/SourceFiles/media/player/media_player_button.cpp b/Telegram/SourceFiles/media/player/media_player_button.cpp index 4944e9483..118a563ea 100644 --- a/Telegram/SourceFiles/media/player/media_player_button.cpp +++ b/Telegram/SourceFiles/media/player/media_player_button.cpp @@ -24,25 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Media { namespace Player { -namespace { - -template -QPainterPath interpolatePaths(QPointF (&from)[N], QPointF (&to)[N], float64 k) { - static_assert(N > 1, "Wrong points count in path!"); - - auto from_coef = 1. - k, to_coef = k; - QPainterPath result; - auto x = from[0].x() * from_coef + to[0].x() * to_coef; - auto y = from[0].y() * from_coef + to[0].y() * to_coef; - result.moveTo(x, y); - for (int i = 1; i != N; ++i) { - result.lineTo(from[i].x() * from_coef + to[i].x() * to_coef, from[i].y() * from_coef + to[i].y() * to_coef); - } - result.lineTo(x, y); - return result; -} - -} // namespace PlayButtonLayout::PlayButtonLayout(const style::MediaPlayerButton &st, base::lambda callback) : _st(st) @@ -151,7 +132,7 @@ void PlayButtonLayout::paintPlayToPause(Painter &p, const QBrush &brush, float64 { playLeft + (playWidth / 2.), playTop + (3 * playHeight / 4.) }, { playLeft, playTop + playHeight }, }; - p.fillPath(interpolatePaths(pathLeftPlay, pathLeftPause, progress), brush); + p.fillPath(anim::interpolate(pathLeftPlay, pathLeftPause, progress), brush); QPointF pathRightPause[] = { { pauseLeft + pauseWidth - pauseStroke, pauseTop }, @@ -165,7 +146,7 @@ void PlayButtonLayout::paintPlayToPause(Painter &p, const QBrush &brush, float64 { playLeft + playWidth, playTop + (playHeight / 2.) }, { playLeft + (playWidth / 2.), playTop + (3 * playHeight / 4.) }, }; - p.fillPath(interpolatePaths(pathRightPlay, pathRightPause, progress), brush); + p.fillPath(anim::interpolate(pathRightPlay, pathRightPause, progress), brush); } void PlayButtonLayout::paintPlayToCancel(Painter &p, const QBrush &brush, float64 progress) { @@ -213,7 +194,7 @@ void PlayButtonLayout::paintPlayToCancel(Painter &p, const QBrush &brush, float6 { cancelLeft, cancelTop + cancelHeight - cancelStroke }, { cancelLeft + (cancelWidth / 2.) - cancelStroke, cancelTop + (cancelHeight / 2.) }, }; - p.fillPath(interpolatePaths(pathPlay, pathCancel, progress), brush); + p.fillPath(anim::interpolate(pathPlay, pathCancel, progress), brush); } void PlayButtonLayout::paintPauseToCancel(Painter &p, const QBrush &brush, float64 progress) { @@ -246,7 +227,7 @@ void PlayButtonLayout::paintPauseToCancel(Painter &p, const QBrush &brush, float { cancelLeft + cancelWidth, cancelTop + cancelHeight - cancelStroke }, { cancelLeft + cancelWidth - cancelStroke, cancelTop + cancelHeight }, }; - p.fillPath(interpolatePaths(pathLeftPause, pathLeftCancel, progress), brush); + p.fillPath(anim::interpolate(pathLeftPause, pathLeftCancel, progress), brush); QPointF pathRightPause[] = { { pauseLeft + pauseWidth - pauseStroke, pauseTop }, @@ -260,7 +241,7 @@ void PlayButtonLayout::paintPauseToCancel(Painter &p, const QBrush &brush, float { cancelLeft + cancelStroke, cancelTop + cancelHeight }, { cancelLeft, cancelTop + cancelHeight - cancelStroke }, }; - p.fillPath(interpolatePaths(pathRightPause, pathRightCancel, progress), brush); + p.fillPath(anim::interpolate(pathRightPause, pathRightCancel, progress), brush); } void PlayButtonLayout::animationCallback() { diff --git a/Telegram/SourceFiles/ui/abstract_button.h b/Telegram/SourceFiles/ui/abstract_button.h index a436cfcfa..a564ab56a 100644 --- a/Telegram/SourceFiles/ui/abstract_button.h +++ b/Telegram/SourceFiles/ui/abstract_button.h @@ -44,7 +44,7 @@ public: bool isDown() const { return _state & StateFlag::Down; } - bool isDisabled() { + bool isDisabled() const { return _state & StateFlag::Disabled; } diff --git a/Telegram/SourceFiles/ui/animation.h b/Telegram/SourceFiles/ui/animation.h index d8359ce23..0893ac164 100644 --- a/Telegram/SourceFiles/ui/animation.h +++ b/Telegram/SourceFiles/ui/animation.h @@ -386,6 +386,37 @@ FORCE_INLINE QBrush brush(style::color a, style::color b, float64 b_ratio) { return (b_ratio > 0) ? ((b_ratio < 1) ? brush(a->c, b->c, b_ratio) : b) : a; } +template +QPainterPath interpolate(QPointF (&from)[N], QPointF (&to)[N], float64 k) { + static_assert(N > 1, "Wrong points count in path!"); + + auto from_coef = 1. - k, to_coef = k; + QPainterPath result; + auto x = from[0].x() * from_coef + to[0].x() * to_coef; + auto y = from[0].y() * from_coef + to[0].y() * to_coef; + result.moveTo(x, y); + for (int i = 1; i != N; ++i) { + result.lineTo(from[i].x() * from_coef + to[i].x() * to_coef, from[i].y() * from_coef + to[i].y() * to_coef); + } + result.lineTo(x, y); + return result; +} + +template +QPainterPath path(QPointF (&from)[N]) { + static_assert(N > 1, "Wrong points count in path!"); + + QPainterPath result; + auto x = from[0].x(); + auto y = from[0].y(); + result.moveTo(x, y); + for (int i = 1; i != N; ++i) { + result.lineTo(from[i].x(), from[i].y()); + } + result.lineTo(x, y); + return result; +} + }; class BasicAnimation; diff --git a/Telegram/SourceFiles/ui/text/text_entity.cpp b/Telegram/SourceFiles/ui/text/text_entity.cpp index 15611dada..5d2836fdd 100644 --- a/Telegram/SourceFiles/ui/text/text_entity.cpp +++ b/Telegram/SourceFiles/ui/text/text_entity.cpp @@ -44,7 +44,7 @@ QString ExpressionMailNameAtEnd() { } QString ExpressionSeparators(const QString &additional) { - return qsl("\\s\\.,:;<>|'\"\\[\\]\\{\\}\\~\\!\\%\\^\\(\\)\\-\\+=\\x10") + additional; + return qsl("\\s\\.,:;<>|'\"\\[\\]\\{\\}\\~\\!\\?\\%\\^\\(\\)\\-\\+=\\x10") + additional; } QString ExpressionHashtag() { diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp index a900ad3c1..bfdcdf01a 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.cpp +++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp @@ -107,7 +107,7 @@ void RippleButton::onStateChanged(State was, StateChangeSource source) { if (down && (source == StateChangeSource::ByPress)) { // Start a ripple only from mouse press. auto position = prepareRippleStartPosition(); - if (position != disabledRippleStartPosition()) { + if (position != DisabledRippleStartPosition()) { ensureRipple(); _ripple->add(position); } diff --git a/Telegram/SourceFiles/ui/widgets/buttons.h b/Telegram/SourceFiles/ui/widgets/buttons.h index b9cceafe2..9e63c4b88 100644 --- a/Telegram/SourceFiles/ui/widgets/buttons.h +++ b/Telegram/SourceFiles/ui/widgets/buttons.h @@ -63,6 +63,10 @@ public: return _forceRippled; } + static QPoint DisabledRippleStartPosition() { + return QPoint(-0x3FFFFFFF, -0x3FFFFFFF); + } + ~RippleButton(); protected: @@ -72,9 +76,6 @@ protected: virtual QImage prepareRippleMask() const; virtual QPoint prepareRippleStartPosition() const; - QPoint disabledRippleStartPosition() const { - return QPoint(-0x3FFFFFFF, -0x3FFFFFFF); - } void resetRipples(); private: diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.cpp b/Telegram/SourceFiles/ui/widgets/checkbox.cpp index 909670e3e..7644a72b6 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.cpp +++ b/Telegram/SourceFiles/ui/widgets/checkbox.cpp @@ -75,8 +75,8 @@ ToggleView::ToggleView(const style::Toggle &st, bool checked, base::lambdadiameter + _st->width, _st->diameter); +QSize ToggleView::getSize() const { + return QSize(2 * _st->border + _st->diameter + _st->width, 2 * _st->border + _st->diameter); } void ToggleView::setStyle(const style::Toggle &st) { @@ -84,16 +84,21 @@ void ToggleView::setStyle(const style::Toggle &st) { } void ToggleView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) { + left += _st->border; + top += _st->border; + PainterHighQualityEnabler hq(p); auto toggled = currentAnimationValue(ms); auto fullWidth = _st->diameter + _st->width; auto innerDiameter = _st->diameter - 2 * _st->shift; auto innerRadius = float64(innerDiameter) / 2.; + auto toggleLeft = left + anim::interpolate(0, fullWidth - _st->diameter, toggled); auto bgRect = rtlrect(left + _st->shift, top + _st->shift, fullWidth - 2 * _st->shift, innerDiameter, outerWidth); - auto fgRect = rtlrect(left + anim::interpolate(0, fullWidth - _st->diameter, toggled), top, _st->diameter, _st->diameter, outerWidth); + auto fgRect = rtlrect(toggleLeft, top, _st->diameter, _st->diameter, outerWidth); + auto fgBrush = anim::brush(_st->untoggledFg, _st->toggledFg, toggled); p.setPen(Qt::NoPen); - p.setBrush(anim::brush(_st->untoggledFg, _st->toggledFg, toggled)); + p.setBrush(fgBrush); p.drawRoundedRect(bgRect, innerRadius, innerRadius); auto pen = anim::pen(_st->untoggledFg, _st->toggledFg, toggled); @@ -101,13 +106,112 @@ void ToggleView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) p.setPen(pen); p.setBrush(anim::brush(_st->untoggledBg, _st->toggledBg, toggled)); p.drawEllipse(fgRect); + + if (_st->xsize > 0) { + paintXV(p, toggleLeft, top, outerWidth, toggled, fgBrush); + } +} + +void ToggleView::paintXV(Painter &p, int left, int top, int outerWidth, float64 toggled, const QBrush &brush) { + t_assert(_st->vsize > 0); + t_assert(_st->stroke > 0); + static const auto sqrt2 = sqrt(2.); + auto stroke = (0. + _st->stroke) / sqrt2; + if (toggled < 1) { + // Just X or X->V. + auto xSize = 0. + _st->xsize; + auto xLeft = left + (_st->diameter - xSize) / 2.; + auto xTop = top + (_st->diameter - xSize) / 2.; + QPointF pathX[] = { + { xLeft, xTop + stroke }, + { xLeft + stroke, xTop }, + { xLeft + (xSize / 2.), xTop + (xSize / 2.) - stroke }, + { xLeft + xSize - stroke, xTop }, + { xLeft + xSize, xTop + stroke }, + { xLeft + (xSize / 2.) + stroke, xTop + (xSize / 2.) }, + { xLeft + xSize, xTop + xSize - stroke }, + { xLeft + xSize - stroke, xTop + xSize }, + { xLeft + (xSize / 2.), xTop + (xSize / 2.) + stroke }, + { xLeft + stroke, xTop + xSize }, + { xLeft, xTop + xSize - stroke }, + { xLeft + (xSize / 2.) - stroke, xTop + (xSize / 2.) }, + }; + for (auto &point : pathX) { + point = rtlpoint(point, outerWidth); + } + if (toggled > 0) { + // X->V. + auto vSize = 0. + _st->vsize; + auto fSize = (xSize + vSize - 2. * stroke); + auto vLeft = left + (_st->diameter - fSize) / 2.; + auto vTop = 0. + xTop + _st->vshift; + QPointF pathV[] = { + { vLeft, vTop + xSize - vSize + stroke }, + { vLeft + stroke, vTop + xSize - vSize }, + { vLeft + vSize - stroke, vTop + xSize - 2 * stroke }, + { vLeft + fSize - stroke, vTop }, + { vLeft + fSize, vTop + stroke }, + { vLeft + vSize, vTop + xSize - stroke }, + { vLeft + vSize, vTop + xSize - stroke }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - 2 * stroke, vTop + xSize - stroke }, + { vLeft + vSize - 2 * stroke, vTop + xSize - stroke }, + }; + for (auto &point : pathV) { + point = rtlpoint(point, outerWidth); + } + p.fillPath(anim::interpolate(pathX, pathV, toggled), brush); + } else { + // Just X. + p.fillPath(anim::path(pathX), brush); + } + } else { + // Just V. + auto xSize = 0. + _st->xsize; + auto xTop = top + (_st->diameter - xSize) / 2.; + auto vSize = 0. + _st->vsize; + auto fSize = (xSize + vSize - 2. * stroke); + auto vLeft = left + (_st->diameter - (_st->xsize + _st->vsize - 2. * stroke)) / 2.; + auto vTop = 0. + xTop + _st->vshift; + QPointF pathV[] = { + { vLeft, vTop + xSize - vSize + stroke }, + { vLeft + stroke, vTop + xSize - vSize }, + { vLeft + vSize - stroke, vTop + xSize - 2 * stroke }, + { vLeft + fSize - stroke, vTop }, + { vLeft + fSize, vTop + stroke }, + { vLeft + vSize, vTop + xSize - stroke }, + { vLeft + vSize, vTop + xSize - stroke }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - stroke, vTop + xSize }, + { vLeft + vSize - 2 * stroke, vTop + xSize - stroke }, + { vLeft + vSize - 2 * stroke, vTop + xSize - stroke }, + }; + + p.fillPath(anim::path(pathV), brush); + } +} + +QSize ToggleView::rippleSize() const { + return getSize() + 2 * QSize(_st->rippleAreaPadding, _st->rippleAreaPadding); +} + +QImage ToggleView::prepareRippleMask() const { + auto size = rippleSize(); + return RippleAnimation::roundRectMask(size, size.height() / 2); +} + +bool ToggleView::checkRippleStartPosition(QPoint position) const { + return QRect(QPoint(0, 0), rippleSize()).contains(position); } CheckView::CheckView(const style::Check &st, bool checked, base::lambda updateCallback) : AbstractCheckView(st.duration, checked, std::move(updateCallback)) , _st(&st) { } -QSize CheckView::getSize() { +QSize CheckView::getSize() const { return QSize(_st->diameter, _st->diameter); } @@ -132,11 +236,23 @@ void CheckView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) } } +QSize CheckView::rippleSize() const { + return getSize() + 2 * QSize(_st->rippleAreaPadding, _st->rippleAreaPadding); +} + +QImage CheckView::prepareRippleMask() const { + return RippleAnimation::ellipseMask(rippleSize()); +} + +bool CheckView::checkRippleStartPosition(QPoint position) const { + return QRect(QPoint(0, 0), rippleSize()).contains(position); +} + RadioView::RadioView(const style::Radio &st, bool checked, base::lambda updateCallback) : AbstractCheckView(st.duration, checked, std::move(updateCallback)) , _st(&st) { } -QSize RadioView::getSize() { +QSize RadioView::getSize() const { return QSize(_st->diameter, _st->diameter); } @@ -176,6 +292,18 @@ void RadioView::paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) } } +QSize RadioView::rippleSize() const { + return getSize() + 2 * QSize(_st->rippleAreaPadding, _st->rippleAreaPadding); +} + +QImage RadioView::prepareRippleMask() const { + return RippleAnimation::ellipseMask(rippleSize()); +} + +bool RadioView::checkRippleStartPosition(QPoint position) const { + return QRect(QPoint(0, 0), rippleSize()).contains(position); +} + Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st, const style::Check &checkSt) : Checkbox(parent, text, st, std::make_unique(checkSt, checked, [this] { updateCheck(); })) { } @@ -230,9 +358,13 @@ void Checkbox::paintEvent(QPaintEvent *e) { Painter p(this); auto ms = getms(); - auto active = _check->currentAnimationValue(ms); - auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); - paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &color); + if (isDisabled()) { + p.setOpacity(_st.disabledOpacity); + } else { + auto active = _check->currentAnimationValue(ms); + auto color = anim::color(_st.rippleBg, _st.rippleBgActive, active); + paintRipple(p, _st.rippleAreaPosition.x(), _st.rippleAreaPosition.y(), ms, &color); + } auto realCheckRect = myrtlrect(_checkRect); if (realCheckRect.intersects(e->rect())) { @@ -251,6 +383,7 @@ void Checkbox::onStateChanged(State was, StateChangeSource source) { if (isDisabled() && !(was & StateFlag::Disabled)) { setCursor(style::cur_default); + finishAnimations(); } else if (!isDisabled() && (was & StateFlag::Disabled)) { setCursor(style::cur_pointer); } @@ -264,19 +397,19 @@ void Checkbox::onStateChanged(State was, StateChangeSource source) { } int Checkbox::resizeGetHeight(int newWidth) { - return _st.height; + return _st.height ? _st.height : _check->getSize().height(); } QImage Checkbox::prepareRippleMask() const { - return RippleAnimation::ellipseMask(QSize(_st.rippleAreaSize, _st.rippleAreaSize)); + return _check->prepareRippleMask(); } QPoint Checkbox::prepareRippleStartPosition() const { - auto position = mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; - if (QRect(0, 0, _st.rippleAreaSize, _st.rippleAreaSize).contains(position)) { - return position; + if (isDisabled()) { + return DisabledRippleStartPosition(); } - return disabledRippleStartPosition(); + auto position = mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; + return _check->checkRippleStartPosition(position) ? position : DisabledRippleStartPosition(); } void RadiobuttonGroup::setValue(int value) { diff --git a/Telegram/SourceFiles/ui/widgets/checkbox.h b/Telegram/SourceFiles/ui/widgets/checkbox.h index 2465bc299..7d51693f5 100644 --- a/Telegram/SourceFiles/ui/widgets/checkbox.h +++ b/Telegram/SourceFiles/ui/widgets/checkbox.h @@ -38,11 +38,13 @@ public: } float64 currentAnimationValue(TimeMs ms); - virtual QSize getSize() = 0; + virtual QSize getSize() const = 0; // Zero instead of ms value means that animation was already updated for this time. // It can be passed to currentAnimationValue() safely. virtual void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) = 0; + virtual QImage prepareRippleMask() const = 0; + virtual bool checkRippleStartPosition(QPoint position) const = 0; void paint(Painter &p, int left, int top, int outerWidth) { // Pass zero in ms if the animation was already updated for this time. @@ -65,10 +67,14 @@ public: void setStyle(const style::Check &st); - QSize getSize() override; + QSize getSize() const override; void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) override; + QImage prepareRippleMask() const override; + bool checkRippleStartPosition(QPoint position) const override; private: + QSize rippleSize() const; + gsl::not_null _st; }; @@ -79,10 +85,14 @@ public: void setStyle(const style::Radio &st); - QSize getSize() override; + QSize getSize() const override; void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) override; + QImage prepareRippleMask() const override; + bool checkRippleStartPosition(QPoint position) const override; private: + QSize rippleSize() const; + gsl::not_null _st; }; @@ -93,10 +103,15 @@ public: void setStyle(const style::Toggle &st); - QSize getSize() override; + QSize getSize() const override; void paint(Painter &p, int left, int top, int outerWidth, TimeMs ms) override; + QImage prepareRippleMask() const override; + bool checkRippleStartPosition(QPoint position) const override; private: + void paintXV(Painter &p, int left, int top, int outerWidth, float64 toggled, const QBrush &brush); + QSize rippleSize() const; + gsl::not_null _st; }; diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style index 7e61e1e65..14bc207d6 100644 --- a/Telegram/SourceFiles/ui/widgets/widgets.style +++ b/Telegram/SourceFiles/ui/widgets/widgets.style @@ -102,6 +102,11 @@ Toggle { shift: pixels; diameter: pixels; width: pixels; + xsize: pixels; + vsize: pixels; + vshift: pixels; + stroke: pixels; + rippleAreaPadding: pixels; } Check { @@ -112,6 +117,7 @@ Check { thickness: pixels; icon: icon; duration: int; + rippleAreaPadding: pixels; } Radio { @@ -122,6 +128,7 @@ Radio { thickness: pixels; skip: pixels; duration: int; + rippleAreaPadding: pixels; } Checkbox { @@ -136,10 +143,11 @@ Checkbox { style: TextStyle; rippleAreaPosition: point; - rippleAreaSize: pixels; rippleBg: color; rippleBgActive: color; ripple: RippleAnimation; + + disabledOpacity: double; } ScrollArea { @@ -679,6 +687,7 @@ defaultCheck: Check { thickness: 2px; icon: defaultCheckboxIcon; duration: 120; + rippleAreaPadding: 8px; } defaultRadio: Radio { bg: transparent; @@ -688,6 +697,7 @@ defaultRadio: Radio { thickness: 2px; skip: 65px; // * 0.1 duration: 120; + rippleAreaPadding: 8px; } defaultToggle: Toggle { toggledBg: windowBg; @@ -699,23 +709,28 @@ defaultToggle: Toggle { shift: 1px; diameter: 20px; width: 16px; + xsize: 0px; + vsize: 0px; + vshift: 0px; + stroke: 0px; + rippleAreaPadding: 8px; } defaultCheckbox: Checkbox { textFg: windowFg; width: -44px; - height: 22px; margin: margins(8px, 8px, 8px, 8px); textPosition: point(10px, 2px); style: defaultTextStyle; - rippleAreaSize: 38px; rippleAreaPosition: point(0px, 0px); rippleBg: windowBgOver; rippleBgActive: lightButtonBgOver; ripple: defaultRippleAnimation; + + disabledOpacity: 0.5; } defaultIconButton: IconButton {