From 1647b0b76a3352f5d9b2892441eeaf002256a481 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Sat, 25 Apr 2020 21:03:42 +0400 Subject: [PATCH 1/7] Fix setWeight order --- ui/style/style_core_font.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ui/style/style_core_font.cpp b/ui/style/style_core_font.cpp index 0cd6580..88c359b 100644 --- a/ui/style/style_core_font.cpp +++ b/ui/style/style_core_font.cpp @@ -288,18 +288,18 @@ FontData::FontData(int size, uint32 flags, int family, Font *other) f.setFamily(GetFontOverride(flags)); } -#ifdef DESKTOP_APP_USE_PACKAGED_FONTS - if (_flags & FontSemibold) { - f.setWeight(QFont::DemiBold); - } -#endif // DESKTOP_APP_USE_PACKAGED_FONTS - f.setPixelSize(size); f.setBold(_flags & FontBold); f.setItalic(_flags & FontItalic); f.setUnderline(_flags & FontUnderline); f.setStrikeOut(_flags & FontStrikeOut); +#ifdef DESKTOP_APP_USE_PACKAGED_FONTS + if (_flags & FontSemibold) { + f.setWeight(QFont::DemiBold); + } +#endif // DESKTOP_APP_USE_PACKAGED_FONTS + m = QFontMetrics(f); height = m.height(); ascent = m.ascent(); From 48a83157407c555d3a0c17026aced41308138d49 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 29 Apr 2020 18:52:18 +0400 Subject: [PATCH 2/7] Introduce a toast style structure. --- ui/basic.style | 11 --------- ui/toast/toast.cpp | 20 ++++++++------- ui/toast/toast.h | 10 +++++--- ui/toast/toast_widget.cpp | 52 +++++++++++++++++++++++++++------------ ui/toast/toast_widget.h | 7 ++---- ui/widgets/widgets.style | 26 ++++++++++++++++++++ 6 files changed, 82 insertions(+), 44 deletions(-) diff --git a/ui/basic.style b/ui/basic.style index 9d0a66a..6c49f39 100644 --- a/ui/basic.style +++ b/ui/basic.style @@ -268,17 +268,6 @@ inlineRowFileDescriptionTop: 23px; inlineResultsMinWidth: 48px; inlineDurationMargin: 3px; -toastTextStyle: defaultTextStyle; -toastTextPalette: TextPalette(defaultTextPalette) { - linkFg: mediaviewTextLinkFg; - monoFg: mediaviewCaptionFg; -} -toastMaxWidth: 480px; -toastMinMargin: 13px; -toastPadding: margins(19px, 13px, 19px, 12px); -toastFadeInDuration: 200; -toastFadeOutDuration: 1000; - historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }}; historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }}; boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }}; diff --git a/ui/toast/toast.cpp b/ui/toast/toast.cpp index 8c5075b..8bb9879 100644 --- a/ui/toast/toast.cpp +++ b/ui/toast/toast.cpp @@ -8,6 +8,7 @@ #include "ui/toast/toast_manager.h" #include "ui/toast/toast_widget.h" +#include "styles/style_widgets.h" namespace Ui { namespace Toast { @@ -21,13 +22,14 @@ Instance::Instance( const Config &config, not_null widgetParent, const Private &) -: _hideAtMs(crl::now() + config.durationMs) { +: _st(config.st) +, _hideAtMs(crl::now() + config.durationMs) { _widget = std::make_unique(widgetParent, config); _a_opacity.start( [=] { opacityAnimationCallback(); }, 0., 1., - st::toastFadeInDuration); + _st->durationFadeIn); } void SetDefaultParent(not_null parent) { @@ -49,15 +51,11 @@ void Show(const Config &config) { } void Show(not_null parent, const QString &text) { - auto config = Config(); - config.text = { text }; - Show(parent, config); + Show(parent, Config{ .text = { text }, .st = &st::defaultToast }); } void Show(const QString &text) { - auto config = Config(); - config.text = { text }; - Show(config); + Show(Config{ .text = { text }, .st = &st::defaultToast }); } void Instance::opacityAnimationCallback() { @@ -72,7 +70,11 @@ void Instance::opacityAnimationCallback() { void Instance::hideAnimated() { _hiding = true; - _a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::toastFadeOutDuration); + _a_opacity.start( + [=] { opacityAnimationCallback(); }, + 1., + 0., + _st->durationFadeOut); } void Instance::hide() { diff --git a/ui/toast/toast.h b/ui/toast/toast.h index b0e0198..43fef3a 100644 --- a/ui/toast/toast.h +++ b/ui/toast/toast.h @@ -10,6 +10,10 @@ #include "ui/text/text_entity.h" #include "ui/click_handler.h" +namespace style { +struct Toast; +} // namespace style + namespace Ui { namespace Toast { @@ -23,10 +27,8 @@ using ClickHandlerFilter = Fn; inline constexpr auto kDefaultDuration = crl::time(1500); struct Config { TextWithEntities text; - QMargins padding; + not_null st; crl::time durationMs = kDefaultDuration; - int minWidth = 0; - int maxWidth = 0; int maxLines = 16; bool multiline = false; bool dark = false; @@ -56,6 +58,8 @@ public: private: void opacityAnimationCallback(); + const not_null _st; + bool _hiding = false; Ui::Animations::Simple _a_opacity; diff --git a/ui/toast/toast_widget.cpp b/ui/toast/toast_widget.cpp index 933782c..b489cd4 100644 --- a/ui/toast/toast_widget.cpp +++ b/ui/toast/toast_widget.cpp @@ -8,6 +8,7 @@ #include "ui/image/image_prepare.h" #include "styles/palette.h" +#include "styles/style_widgets.h" #include @@ -17,15 +18,14 @@ namespace internal { Widget::Widget(QWidget *parent, const Config &config) : TWidget(parent) +, _st(config.st) , _roundRect(ImageRoundRadius::Large, st::toastBg) , _multiline(config.multiline) , _dark(config.dark) -, _maxWidth((config.maxWidth > 0) ? config.maxWidth : st::toastMaxWidth) -, _padding((config.padding.left() > 0) ? config.padding : st::toastPadding) -, _maxTextWidth(widthWithoutPadding(_maxWidth)) +, _maxTextWidth(widthWithoutPadding(_st->maxWidth)) , _maxTextHeight( - st::toastTextStyle.font->height * (_multiline ? config.maxLines : 1)) -, _text(_multiline ? widthWithoutPadding(config.minWidth) : QFIXED_MAX) + config.st->style.font->height * (_multiline ? config.maxLines : 1)) +, _text(_multiline ? widthWithoutPadding(config.st->minWidth) : QFIXED_MAX) , _clickHandlerFilter(config.filter) { const auto toastOptions = TextParseOptions{ TextParseMultiline, @@ -34,7 +34,7 @@ Widget::Widget(QWidget *parent, const Config &config) Qt::LayoutDirectionAuto }; _text.setMarkedText( - st::toastTextStyle, + _st->style, _multiline ? config.text : TextUtilities::SingleLine(config.text), toastOptions); @@ -49,15 +49,25 @@ Widget::Widget(QWidget *parent, const Config &config) } void Widget::onParentResized() { - auto newWidth = _maxWidth; - accumulate_min(newWidth, _padding.left() + _text.maxWidth() + _padding.right()); - accumulate_min(newWidth, parentWidget()->width() - 2 * st::toastMinMargin); + auto newWidth = _st->maxWidth; + accumulate_min( + newWidth, + _st->padding.left() + _text.maxWidth() + _st->padding.right()); + accumulate_min( + newWidth, + parentWidget()->width() - _st->margin.left() - _st->margin.right()); _textWidth = widthWithoutPadding(newWidth); const auto textHeight = _multiline ? qMin(_text.countHeight(_textWidth), _maxTextHeight) : _text.minHeight(); - const auto newHeight = _padding.top() + textHeight + _padding.bottom(); - setGeometry((parentWidget()->width() - newWidth) / 2, (parentWidget()->height() - newHeight) / 2, newWidth, newHeight); + const auto newHeight = _st->padding.top() + + textHeight + + _st->padding.bottom(); + setGeometry( + (parentWidget()->width() - newWidth) / 2, + (parentWidget()->height() - newHeight) / 2, + newWidth, + newHeight); } void Widget::setShownLevel(float64 shownLevel) { @@ -74,11 +84,16 @@ void Widget::paintEvent(QPaintEvent *e) { _roundRect.paint(p, rect()); } - p.setTextPalette(st::toastTextPalette); + p.setTextPalette(_st->palette); - const auto lines = _maxTextHeight / st::toastTextStyle.font->height; + const auto lines = _maxTextHeight / _st->style.font->height; p.setPen(st::toastFg); - _text.drawElided(p, _padding.left(), _padding.top(), _textWidth + 1, lines); + _text.drawElided( + p, + _st->padding.left(), + _st->padding.top(), + _textWidth + 1, + lines); } void Widget::leaveEventHook(QEvent *e) { @@ -96,8 +111,9 @@ void Widget::mouseMoveEvent(QMouseEvent *e) { if (!_text.hasLinks()) { return; } - const auto point = e->pos() - QPoint(_padding.left(), _padding.top()); - const auto lines = _maxTextHeight / st::toastTextStyle.font->height; + const auto point = e->pos() + - QPoint(_st->padding.left(), _st->padding.top()); + const auto lines = _maxTextHeight / _st->style.font->height; const auto state = _text.getStateElided(point, _textWidth + 1); const auto was = ClickHandler::getActive(); if (was != state.link) { @@ -129,6 +145,10 @@ void Widget::mouseReleaseEvent(QMouseEvent *e) { } } +int Widget::widthWithoutPadding(int w) const { + return w - _st->padding.left() - _st->padding.right(); +} + } // namespace internal } // namespace Toast } // namespace Ui diff --git a/ui/toast/toast_widget.h b/ui/toast/toast_widget.h index 22b6db8..79d91df 100644 --- a/ui/toast/toast_widget.h +++ b/ui/toast/toast_widget.h @@ -33,17 +33,14 @@ protected: void mouseReleaseEvent(QMouseEvent *e) override; private: - int widthWithoutPadding(int w) { - return w - _padding.left() - _padding.right(); - } + [[nodiscard]] int widthWithoutPadding(int w) const; + const not_null _st; RoundRect _roundRect; float64 _shownLevel = 0; bool _multiline = false; bool _dark = false; - int _maxWidth = 0; - QMargins _padding; int _maxTextWidth = 0; int _maxTextHeight = 0; diff --git a/ui/widgets/widgets.style b/ui/widgets/widgets.style index e6e9fae..030af37 100644 --- a/ui/widgets/widgets.style +++ b/ui/widgets/widgets.style @@ -568,6 +568,18 @@ SideBarButton { ripple: RippleAnimation; } +Toast { + style: TextStyle; + palette: TextPalette; + padding: margins; + margin: margins; + minWidth: pixels; + maxWidth: pixels; + durationFadeIn: int; + durationFadeOut: int; + durationSlide: int; +} + defaultLabelSimple: LabelSimple { font: normalFont; maxWidth: 0px; @@ -1266,6 +1278,20 @@ defaultSideBarButton: SideBarButton { } } +defaultToast: Toast { + style: defaultTextStyle; + palette: TextPalette(defaultTextPalette) { + linkFg: mediaviewTextLinkFg; + monoFg: mediaviewCaptionFg; + } + padding: margins(19px, 13px, 19px, 12px); + margin: margins(13px, 13px, 13px, 13px); + maxWidth: 480px; + durationFadeIn: 200; + durationFadeOut: 1000; + durationSlide: 400; +} + // Windows specific title windowTitleButton: IconButton { From 7849f0561b7d8d0e51e3fec3dcfe07e1502c82cc Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 30 Apr 2020 13:16:15 +0400 Subject: [PATCH 3/7] Allow sliding toasts from the parent side. --- ui/toast/toast.cpp | 49 +++++++++++++++++------------ ui/toast/toast.h | 36 +++++++++++++++------- ui/toast/toast_manager.cpp | 23 +++++++++++--- ui/toast/toast_manager.h | 10 ++---- ui/toast/toast_widget.cpp | 63 ++++++++++++++++++++++++++++++-------- ui/toast/toast_widget.h | 4 ++- ui/widgets/widgets.style | 2 +- 7 files changed, 130 insertions(+), 57 deletions(-) diff --git a/ui/toast/toast.cpp b/ui/toast/toast.cpp index 8bb9879..b2016ba 100644 --- a/ui/toast/toast.cpp +++ b/ui/toast/toast.cpp @@ -23,45 +23,50 @@ Instance::Instance( not_null widgetParent, const Private &) : _st(config.st) -, _hideAtMs(crl::now() + config.durationMs) { - _widget = std::make_unique(widgetParent, config); - _a_opacity.start( - [=] { opacityAnimationCallback(); }, +, _hideAt(crl::now() + config.durationMs) +, _sliding(config.slideSide != RectPart::None) +, _widget(std::make_unique(widgetParent, config)) { + _shownAnimation.start( + [=] { shownAnimationCallback(); }, 0., 1., - _st->durationFadeIn); + _sliding ? _st->durationSlide : _st->durationFadeIn); } void SetDefaultParent(not_null parent) { DefaultParent = parent; } -void Show(not_null parent, const Config &config) { +base::weak_ptr Show( + not_null parent, + const Config &config) { const auto manager = internal::Manager::instance(parent); - manager->addToast(std::make_unique( + return manager->addToast(std::make_unique( config, parent, Instance::Private())); } -void Show(const Config &config) { +base::weak_ptr Show(const Config &config) { if (const auto parent = DefaultParent.data()) { - Show(parent, config); + return Show(parent, config); } + return nullptr; } -void Show(not_null parent, const QString &text) { - Show(parent, Config{ .text = { text }, .st = &st::defaultToast }); +base::weak_ptr Show( + not_null parent, + const QString &text) { + return Show(parent, Config{ .text = { text }, .st = &st::defaultToast }); } -void Show(const QString &text) { - Show(Config{ .text = { text }, .st = &st::defaultToast }); +base::weak_ptr Show(const QString &text) { + return Show(Config{ .text = { text }, .st = &st::defaultToast }); } -void Instance::opacityAnimationCallback() { - _widget->setShownLevel(_a_opacity.value(_hiding ? 0. : 1.)); - _widget->update(); - if (!_a_opacity.animating()) { +void Instance::shownAnimationCallback() { + _widget->setShownLevel(_shownAnimation.value(_hiding ? 0. : 1.)); + if (!_shownAnimation.animating()) { if (_hiding) { hide(); } @@ -70,11 +75,11 @@ void Instance::opacityAnimationCallback() { void Instance::hideAnimated() { _hiding = true; - _a_opacity.start( - [=] { opacityAnimationCallback(); }, + _shownAnimation.start( + [=] { shownAnimationCallback(); }, 1., 0., - _st->durationFadeOut); + _sliding ? _st->durationSlide : _st->durationFadeOut); } void Instance::hide() { @@ -82,5 +87,9 @@ void Instance::hide() { _widget->deleteLater(); } +not_null Instance::widget() const { + return _widget.get(); +} + } // namespace Toast } // namespace Ui diff --git a/ui/toast/toast.h b/ui/toast/toast.h index 43fef3a..6c2a67c 100644 --- a/ui/toast/toast.h +++ b/ui/toast/toast.h @@ -9,6 +9,9 @@ #include "ui/effects/animations.h" #include "ui/text/text_entity.h" #include "ui/click_handler.h" +#include "ui/rect_part.h" +#include "ui/rp_widget.h" +#include "base/weak_ptr.h" namespace style { struct Toast; @@ -32,15 +35,13 @@ struct Config { int maxLines = 16; bool multiline = false; bool dark = false; + RectPart slideSide = RectPart::None; ClickHandlerFilter filter; }; -void SetDefaultParent(not_null parent); -void Show(not_null parent, const Config &config); -void Show(const Config &config); -void Show(not_null parent, const QString &text); -void Show(const QString &text); -class Instance { +void SetDefaultParent(not_null parent); + +class Instance final : public base::has_weak_ptr { struct Private { }; @@ -55,22 +56,35 @@ public: void hideAnimated(); void hide(); + [[nodiscard]] not_null widget() const; + private: - void opacityAnimationCallback(); + void shownAnimationCallback(); const not_null _st; + const crl::time _hideAt = 0; + Ui::Animations::Simple _shownAnimation; bool _hiding = false; - Ui::Animations::Simple _a_opacity; - - const crl::time _hideAtMs; + bool _sliding = false; // ToastManager should reset _widget pointer if _widget is destroyed. friend class internal::Manager; - friend void Show(not_null parent, const Config &config); + friend base::weak_ptr Show( + not_null parent, + const Config &config); std::unique_ptr _widget; }; +base::weak_ptr Show( + not_null parent, + const Config &config); +base::weak_ptr Show(const Config &config); +base::weak_ptr Show( + not_null parent, + const QString &text); +base::weak_ptr Show(const QString &text); + } // namespace Toast } // namespace Ui diff --git a/ui/toast/toast_manager.cpp b/ui/toast/toast_manager.cpp index adbac76..165af03 100644 --- a/ui/toast/toast_manager.cpp +++ b/ui/toast/toast_manager.cpp @@ -44,13 +44,16 @@ not_null Manager::instance(not_null parent) { return i->second; } -void Manager::addToast(std::unique_ptr &&toast) { +base::weak_ptr Manager::addToast( + std::unique_ptr &&toast) { _toasts.push_back(std::move(toast)); const auto t = _toasts.back().get(); const auto widget = t->_widget.get(); _toastByWidget.emplace(widget, t); - connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(onToastWidgetDestroyed(QObject*))); + connect(widget, &QObject::destroyed, [=] { + toastWidgetDestroyed(widget); + }); if (const auto parent = widget->parentWidget()) { auto found = false; for (auto i = _toastParents.begin(); i != _toastParents.cend();) { @@ -72,10 +75,11 @@ void Manager::addToast(std::unique_ptr &&toast) { const auto nearestHide = _toastByHideTime.empty() ? 0LL : _toastByHideTime.begin()->first; - _toastByHideTime.emplace(t->_hideAtMs, t); + _toastByHideTime.emplace(t->_hideAt, t); if (!nearestHide || _toastByHideTime.begin()->first < nearestHide) { startNextHideTimer(); } + return make_weak(t); } void Manager::hideByTimer() { @@ -92,7 +96,7 @@ void Manager::hideByTimer() { startNextHideTimer(); } -void Manager::onToastWidgetDestroyed(QObject *widget) { +void Manager::toastWidgetDestroyed(QObject *widget) { const auto i = _toastByWidget.find(static_cast(widget)); if (i == _toastByWidget.cend()) { return; @@ -101,6 +105,13 @@ void Manager::onToastWidgetDestroyed(QObject *widget) { _toastByWidget.erase(i); toast->_widget.release(); + for (auto i = begin(_toastByHideTime); i != end(_toastByHideTime); ++i) { + if (i->second == toast) { + _toastByHideTime.erase(i); + break; + } + } + const auto j = ranges::find( _toasts, toast.get(), @@ -111,7 +122,9 @@ void Manager::onToastWidgetDestroyed(QObject *widget) { } void Manager::startNextHideTimer() { - if (_toastByHideTime.empty()) return; + if (_toastByHideTime.empty()) { + return; + } auto ms = crl::now(); if (ms >= _toastByHideTime.begin()->first) { diff --git a/ui/toast/toast_manager.h b/ui/toast/toast_manager.h index c094260..224b8f2 100644 --- a/ui/toast/toast_manager.h +++ b/ui/toast/toast_manager.h @@ -14,9 +14,7 @@ namespace Toast { namespace internal { class Widget; -class Manager : public QObject { - Q_OBJECT - +class Manager final : public QObject { struct CreateTag { }; @@ -28,15 +26,13 @@ public: static not_null instance(not_null parent); - void addToast(std::unique_ptr &&toast); + base::weak_ptr addToast(std::unique_ptr &&toast); protected: bool eventFilter(QObject *o, QEvent *e); -private slots: - void onToastWidgetDestroyed(QObject *widget); - private: + void toastWidgetDestroyed(QObject *widget); void startNextHideTimer(); void hideByTimer(); diff --git a/ui/toast/toast_widget.cpp b/ui/toast/toast_widget.cpp index b489cd4..e0130a1 100644 --- a/ui/toast/toast_widget.cpp +++ b/ui/toast/toast_widget.cpp @@ -17,9 +17,10 @@ namespace Toast { namespace internal { Widget::Widget(QWidget *parent, const Config &config) -: TWidget(parent) +: RpWidget(parent) , _st(config.st) , _roundRect(ImageRoundRadius::Large, st::toastBg) +, _slideSide(config.slideSide) , _multiline(config.multiline) , _dark(config.dark) , _maxTextWidth(widthWithoutPadding(_st->maxWidth)) @@ -49,36 +50,74 @@ Widget::Widget(QWidget *parent, const Config &config) } void Widget::onParentResized() { - auto newWidth = _st->maxWidth; + updateGeometry(); +} + +void Widget::updateGeometry() { + auto width = _st->maxWidth; accumulate_min( - newWidth, + width, _st->padding.left() + _text.maxWidth() + _st->padding.right()); accumulate_min( - newWidth, + width, parentWidget()->width() - _st->margin.left() - _st->margin.right()); - _textWidth = widthWithoutPadding(newWidth); + _textWidth = widthWithoutPadding(width); const auto textHeight = _multiline ? qMin(_text.countHeight(_textWidth), _maxTextHeight) : _text.minHeight(); - const auto newHeight = _st->padding.top() + const auto height = _st->padding.top() + textHeight + _st->padding.bottom(); - setGeometry( - (parentWidget()->width() - newWidth) / 2, - (parentWidget()->height() - newHeight) / 2, - newWidth, - newHeight); + const auto rect = QRect(0, 0, width, height); + const auto outer = parentWidget()->size(); + const auto full = QPoint(outer.width(), outer.height()); + const auto middle = QPoint( + (outer.width() - width) / 2, + (outer.height() - height) / 2); + const auto interpolated = [&](int from, int to) { + return anim::interpolate(from, to, _shownLevel); + }; + setGeometry(rect.translated([&] { + switch (_slideSide) { + case RectPart::None: + return middle; + case RectPart::Left: + return QPoint( + interpolated(-width, _st->margin.left()), + middle.y()); + case RectPart::Top: + return QPoint( + middle.x(), + interpolated(-height, _st->margin.top())); + case RectPart::Right: + return QPoint( + full.x() - interpolated(0, width + _st->margin.right()), + middle.y()); + case RectPart::Bottom: + return QPoint( + middle.x(), + full.y() - interpolated(0, height + _st->margin.bottom())); + } + Unexpected("Slide side in Toast::Widget::updateGeometry."); + }())); } void Widget::setShownLevel(float64 shownLevel) { _shownLevel = shownLevel; + if (_slideSide != RectPart::None) { + updateGeometry(); + } else { + update(); + } } void Widget::paintEvent(QPaintEvent *e) { Painter p(this); PainterHighQualityEnabler hq(p); - p.setOpacity(_shownLevel); + if (_slideSide == RectPart::None) { + p.setOpacity(_shownLevel); + } _roundRect.paint(p, rect()); if (_dark) { _roundRect.paint(p, rect()); diff --git a/ui/toast/toast_widget.h b/ui/toast/toast_widget.h index 79d91df..431bdfd 100644 --- a/ui/toast/toast_widget.h +++ b/ui/toast/toast_widget.h @@ -15,7 +15,7 @@ namespace Ui { namespace Toast { namespace internal { -class Widget : public TWidget { +class Widget final : public RpWidget { public: Widget(QWidget *parent, const Config &config); @@ -34,9 +34,11 @@ protected: private: [[nodiscard]] int widthWithoutPadding(int w) const; + void updateGeometry(); const not_null _st; RoundRect _roundRect; + RectPart _slideSide = RectPart::None; float64 _shownLevel = 0; bool _multiline = false; diff --git a/ui/widgets/widgets.style b/ui/widgets/widgets.style index 030af37..d020ef6 100644 --- a/ui/widgets/widgets.style +++ b/ui/widgets/widgets.style @@ -1289,7 +1289,7 @@ defaultToast: Toast { maxWidth: 480px; durationFadeIn: 200; durationFadeOut: 1000; - durationSlide: 400; + durationSlide: 160; } // Windows specific title From 66e44506dc1cdea5a47dd0124c98d269b2a02d03 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 30 Apr 2020 14:50:34 +0400 Subject: [PATCH 4/7] Support tooltips with an icon. --- ui/toast/toast_widget.cpp | 23 ++++++++++++++++++----- ui/toast/toast_widget.h | 2 ++ ui/widgets/widgets.style | 2 ++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ui/toast/toast_widget.cpp b/ui/toast/toast_widget.cpp index e0130a1..3f8f2a0 100644 --- a/ui/toast/toast_widget.cpp +++ b/ui/toast/toast_widget.cpp @@ -62,12 +62,17 @@ void Widget::updateGeometry() { width, parentWidget()->width() - _st->margin.left() - _st->margin.right()); _textWidth = widthWithoutPadding(width); - const auto textHeight = _multiline + _textHeight = _multiline ? qMin(_text.countHeight(_textWidth), _maxTextHeight) : _text.minHeight(); - const auto height = _st->padding.top() - + textHeight + const auto minHeight = _st->icon.empty() + ? 0 + : (_st->icon.height() + 2 * _st->iconPosition.y()); + const auto normalHeight = _st->padding.top() + + _textHeight + _st->padding.bottom(); + const auto height = std::max(minHeight, normalHeight); + _textTop = _st->padding.top() + ((height - normalHeight) / 2); const auto rect = QRect(0, 0, width, height); const auto outer = parentWidget()->size(); const auto full = QPoint(outer.width(), outer.height()); @@ -123,6 +128,14 @@ void Widget::paintEvent(QPaintEvent *e) { _roundRect.paint(p, rect()); } + if (!_st->icon.empty()) { + _st->icon.paint( + p, + _st->iconPosition.x(), + _st->iconPosition.y(), + width()); + } + p.setTextPalette(_st->palette); const auto lines = _maxTextHeight / _st->style.font->height; @@ -130,7 +143,7 @@ void Widget::paintEvent(QPaintEvent *e) { _text.drawElided( p, _st->padding.left(), - _st->padding.top(), + _textTop, _textWidth + 1, lines); } @@ -151,7 +164,7 @@ void Widget::mouseMoveEvent(QMouseEvent *e) { return; } const auto point = e->pos() - - QPoint(_st->padding.left(), _st->padding.top()); + - QPoint(_st->padding.left(), _textTop); const auto lines = _maxTextHeight / _st->style.font->height; const auto state = _text.getStateElided(point, _textWidth + 1); const auto was = ClickHandler::getActive(); diff --git a/ui/toast/toast_widget.h b/ui/toast/toast_widget.h index 431bdfd..1ec5e97 100644 --- a/ui/toast/toast_widget.h +++ b/ui/toast/toast_widget.h @@ -47,6 +47,8 @@ private: int _maxTextWidth = 0; int _maxTextHeight = 0; int _textWidth = 0; + int _textHeight = 0; + int _textTop = 0; Text::String _text; ClickHandlerFilter _clickHandlerFilter; diff --git a/ui/widgets/widgets.style b/ui/widgets/widgets.style index d020ef6..71d3601 100644 --- a/ui/widgets/widgets.style +++ b/ui/widgets/widgets.style @@ -570,6 +570,8 @@ SideBarButton { Toast { style: TextStyle; + icon: icon; + iconPosition: point; palette: TextPalette; padding: margins; margin: margins; From ce0619daddd55b65fd29db1e865d532eb43e8753 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 29 Apr 2020 11:49:47 +0400 Subject: [PATCH 5/7] Use the same margins for different controls. --- ui/layers/layers.style | 6 +++--- ui/widgets/widgets.style | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/layers/layers.style b/ui/layers/layers.style index 0b22d9b..ddb32ea 100644 --- a/ui/layers/layers.style +++ b/ui/layers/layers.style @@ -85,13 +85,13 @@ boxTitle: FlatLabel(defaultFlatLabel) { linkFontOver: font(17px semibold underline); } } -boxTitlePosition: point(23px, 16px); +boxTitlePosition: point(22px, 16px); boxTitleHeight: 56px; boxTitleAdditionalSkip: 9px; boxTitleAdditionalFont: normalFont; boxScroll: defaultSolidScroll; -boxRowPadding: margins(23px, 0px, 23px, 0px); +boxRowPadding: margins(22px, 0px, 22px, 0px); boxTopMargin: 6px; @@ -121,7 +121,7 @@ boxOptionInputSkip: 6px; boxVerticalMargin: 10px; boxWidth: 320px; boxWideWidth: 364px; -boxPadding: margins(23px, 30px, 23px, 8px); +boxPadding: margins(22px, 30px, 22px, 8px); boxMaxListHeight: 492px; boxLittleSkip: 10px; boxMediumSkip: 20px; diff --git a/ui/widgets/widgets.style b/ui/widgets/widgets.style index 71d3601..b39af53 100644 --- a/ui/widgets/widgets.style +++ b/ui/widgets/widgets.style @@ -1262,7 +1262,7 @@ defaultSettingsButton: SettingsButton { toggle: defaultSettingsToggle; toggleOver: defaultSettingsToggleOver; - toggleSkip: 23px; + toggleSkip: 22px; ripple: defaultRippleAnimation; } From 9086052985c02fed7c7f6990ab9462c2e9ec8f14 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 30 Apr 2020 17:18:04 +0400 Subject: [PATCH 6/7] Fix build on Xcode. --- ui/toast/toast_manager.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ui/toast/toast_manager.h b/ui/toast/toast_manager.h index 224b8f2..f60f22b 100644 --- a/ui/toast/toast_manager.h +++ b/ui/toast/toast_manager.h @@ -37,7 +37,6 @@ private: void hideByTimer(); base::Timer _hideTimer; - crl::time _nextHide = 0; base::flat_multi_map> _toastByHideTime; base::flat_map, not_null> _toastByWidget; From 124b9880d4c56c019da6bc679de9919cf6779780 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 May 2020 12:58:12 +0400 Subject: [PATCH 7/7] Increment emoji cache version. --- ui/emoji_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/emoji_config.cpp b/ui/emoji_config.cpp index ac96452..38eacbc 100644 --- a/ui/emoji_config.cpp +++ b/ui/emoji_config.cpp @@ -32,7 +32,7 @@ constexpr auto kImagesPerRow = 32; constexpr auto kImageRowsPerSprite = 16; constexpr auto kSetVersion = uint32(1); -constexpr auto kCacheVersion = uint32(3); +constexpr auto kCacheVersion = uint32(4); constexpr auto kMaxId = uint32(1 << 8); constexpr auto kScaleForTouchBar = 150;