From ad356135e4f6b92c6fb7453cc22792d8398dd698 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 1 Aug 2023 19:05:07 +0200 Subject: [PATCH] Improve toasts: adaptive, with a title. --- ui/toast/toast.h | 2 ++ ui/toast/toast_widget.cpp | 26 ++++++++++++++++++++++++- ui/toast/toast_widget.h | 1 + ui/widgets/tooltip.cpp | 40 ++++++++++++++++++++++++++------------- ui/widgets/tooltip.h | 5 +++++ 5 files changed, 60 insertions(+), 14 deletions(-) diff --git a/ui/toast/toast.h b/ui/toast/toast.h index b34f0eb..3352942 100644 --- a/ui/toast/toast.h +++ b/ui/toast/toast.h @@ -33,10 +33,12 @@ using ClickHandlerFilter = Fn; inline constexpr auto kDefaultDuration = crl::time(1500); struct Config { + QString title; TextWithEntities text; not_null st = &st::defaultMultilineToast; crl::time duration = kDefaultDuration; int maxLines = 16; + bool adaptive = false; bool multiline = true; bool dark = false; RectPart slideSide = RectPart::None; diff --git a/ui/toast/toast_widget.cpp b/ui/toast/toast_widget.cpp index 6851cc1..c676776 100644 --- a/ui/toast/toast_widget.cpp +++ b/ui/toast/toast_widget.cpp @@ -7,6 +7,8 @@ #include "ui/toast/toast_widget.h" #include "ui/image/image_prepare.h" +#include "ui/text/text_utilities.h" +#include "ui/widgets/tooltip.h" #include "ui/painter.h" #include "styles/palette.h" #include "styles/style_widgets.h" @@ -16,6 +18,21 @@ namespace Ui { namespace Toast { namespace internal { +namespace { + +[[nodiscard]] TextWithEntities ComputeText(const Config &config) { + auto result = config.text; + if (!config.title.isEmpty()) { + result = Text::Bold( + config.title + ).append('\n').append(std::move(result)); + } + return config.multiline + ? result + : TextUtilities::SingleLine(std::move(result)); +} + +} // namespace Widget::Widget(QWidget *parent, const Config &config) : RpWidget(parent) @@ -24,6 +41,7 @@ Widget::Widget(QWidget *parent, const Config &config) , _slideSide(config.slideSide) , _multiline(config.multiline) , _dark(config.dark) +, _adaptive(config.adaptive) , _maxTextWidth(widthWithoutPadding(_st->maxWidth)) , _maxTextHeight( config.st->style.font->height * (_multiline ? config.maxLines : 1)) @@ -37,7 +55,7 @@ Widget::Widget(QWidget *parent, const Config &config) }; _text.setMarkedText( _st->style, - _multiline ? config.text : TextUtilities::SingleLine(config.text), + ComputeText(config), toastOptions, config.textContext ? config.textContext(this) : std::any()); if (_text.hasSpoilers()) { @@ -74,6 +92,12 @@ void Widget::updateGeometry() { accumulate_min( width, parentWidget()->width() - _st->margin.left() - _st->margin.right()); + if (_adaptive) { + const auto added = _st->padding.left() + _st->padding.right(); + width = FindNiceTooltipWidth(0, width - added, [&](int width) { + return _text.countHeight(width); + }) + added; + } _textWidth = widthWithoutPadding(width); _textHeight = _multiline ? qMin(_text.countHeight(_textWidth), _maxTextHeight) diff --git a/ui/toast/toast_widget.h b/ui/toast/toast_widget.h index 1da5e19..cff7e86 100644 --- a/ui/toast/toast_widget.h +++ b/ui/toast/toast_widget.h @@ -45,6 +45,7 @@ private: bool _multiline = false; bool _dark = false; bool _processMouse = false; + bool _adaptive = false; int _maxTextWidth = 0; int _maxTextHeight = 0; diff --git a/ui/widgets/tooltip.cpp b/ui/widgets/tooltip.cpp index c90065d..1613af3 100644 --- a/ui/widgets/tooltip.cpp +++ b/ui/widgets/tooltip.cpp @@ -411,6 +411,25 @@ void ImportantTooltip::paintEvent(QPaintEvent *e) { } } +[[nodiscard]] int FindNiceTooltipWidth( + int minWidth, + int maxWidth, + Fn heightForWidth) { + Expects(minWidth >= 0); + Expects(maxWidth > minWidth); + + const auto desired = heightForWidth(maxWidth); + while (maxWidth - minWidth > 1) { + const auto middle = (minWidth + maxWidth) / 2; + if (heightForWidth(middle) > desired) { + minWidth = middle; + } else { + maxWidth = middle; + } + } + return maxWidth; +} + object_ptr MakeNiceTooltipLabel( QWidget *parent, rpl::producer &&text, @@ -431,19 +450,14 @@ object_ptr MakeNiceTooltipLabel( if (raw->naturalWidth() <= maxWidth) { return; } - const auto desired = raw->heightNoMargins(); - auto from = st.minWidth; - auto till = maxWidth; - while (till - from > 1) { - const auto middle = (from + till) / 2; - raw->resizeToWidth(middle); - if (raw->heightNoMargins() > desired) { - from = middle; - } else { - till = middle; - } - } - raw->resizeToWidth(till); + const auto niceWidth = FindNiceTooltipWidth( + st.minWidth, + maxWidth, + [&](int width) { + raw->resizeToWidth(width); + return raw->heightNoMargins(); + }); + raw->resizeToWidth(niceWidth); }, raw->lifetime()); return result; } diff --git a/ui/widgets/tooltip.h b/ui/widgets/tooltip.h index b5984f1..10d97dc 100644 --- a/ui/widgets/tooltip.h +++ b/ui/widgets/tooltip.h @@ -122,6 +122,11 @@ private: }; +[[nodiscard]] int FindNiceTooltipWidth( + int minWidth, + int maxWidth, + Fn heightForWidth); + [[nodiscard]] object_ptr MakeNiceTooltipLabel( QWidget *parent, rpl::producer &&text,