Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
966cf4d23d
10 changed files with 218 additions and 91 deletions
|
|
@ -268,17 +268,6 @@ inlineRowFileDescriptionTop: 23px;
|
||||||
inlineResultsMinWidth: 48px;
|
inlineResultsMinWidth: 48px;
|
||||||
inlineDurationMargin: 3px;
|
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 }};
|
historyReplyCancelIcon: icon {{ "box_button_close", historyReplyCancelFg }};
|
||||||
historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }};
|
historyReplyCancelIconOver: icon {{ "box_button_close", historyReplyCancelFgOver }};
|
||||||
boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }};
|
boxTitleCloseIcon: icon {{ "box_button_close", boxTitleCloseFg }};
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ constexpr auto kImagesPerRow = 32;
|
||||||
constexpr auto kImageRowsPerSprite = 16;
|
constexpr auto kImageRowsPerSprite = 16;
|
||||||
|
|
||||||
constexpr auto kSetVersion = uint32(1);
|
constexpr auto kSetVersion = uint32(1);
|
||||||
constexpr auto kCacheVersion = uint32(3);
|
constexpr auto kCacheVersion = uint32(4);
|
||||||
constexpr auto kMaxId = uint32(1 << 8);
|
constexpr auto kMaxId = uint32(1 << 8);
|
||||||
|
|
||||||
constexpr auto kScaleForTouchBar = 150;
|
constexpr auto kScaleForTouchBar = 150;
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,13 @@ boxTitle: FlatLabel(defaultFlatLabel) {
|
||||||
linkFontOver: font(17px semibold underline);
|
linkFontOver: font(17px semibold underline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
boxTitlePosition: point(23px, 16px);
|
boxTitlePosition: point(22px, 16px);
|
||||||
boxTitleHeight: 56px;
|
boxTitleHeight: 56px;
|
||||||
boxTitleAdditionalSkip: 9px;
|
boxTitleAdditionalSkip: 9px;
|
||||||
boxTitleAdditionalFont: normalFont;
|
boxTitleAdditionalFont: normalFont;
|
||||||
boxScroll: defaultSolidScroll;
|
boxScroll: defaultSolidScroll;
|
||||||
|
|
||||||
boxRowPadding: margins(23px, 0px, 23px, 0px);
|
boxRowPadding: margins(22px, 0px, 22px, 0px);
|
||||||
|
|
||||||
boxTopMargin: 6px;
|
boxTopMargin: 6px;
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ boxOptionInputSkip: 6px;
|
||||||
boxVerticalMargin: 10px;
|
boxVerticalMargin: 10px;
|
||||||
boxWidth: 320px;
|
boxWidth: 320px;
|
||||||
boxWideWidth: 364px;
|
boxWideWidth: 364px;
|
||||||
boxPadding: margins(23px, 30px, 23px, 8px);
|
boxPadding: margins(22px, 30px, 22px, 8px);
|
||||||
boxMaxListHeight: 492px;
|
boxMaxListHeight: 492px;
|
||||||
boxLittleSkip: 10px;
|
boxLittleSkip: 10px;
|
||||||
boxMediumSkip: 20px;
|
boxMediumSkip: 20px;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "ui/toast/toast_manager.h"
|
#include "ui/toast/toast_manager.h"
|
||||||
#include "ui/toast/toast_widget.h"
|
#include "ui/toast/toast_widget.h"
|
||||||
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Toast {
|
namespace Toast {
|
||||||
|
|
@ -21,49 +22,51 @@ Instance::Instance(
|
||||||
const Config &config,
|
const Config &config,
|
||||||
not_null<QWidget*> widgetParent,
|
not_null<QWidget*> widgetParent,
|
||||||
const Private &)
|
const Private &)
|
||||||
: _hideAtMs(crl::now() + config.durationMs) {
|
: _st(config.st)
|
||||||
_widget = std::make_unique<internal::Widget>(widgetParent, config);
|
, _hideAt(crl::now() + config.durationMs)
|
||||||
_a_opacity.start(
|
, _sliding(config.slideSide != RectPart::None)
|
||||||
[=] { opacityAnimationCallback(); },
|
, _widget(std::make_unique<internal::Widget>(widgetParent, config)) {
|
||||||
|
_shownAnimation.start(
|
||||||
|
[=] { shownAnimationCallback(); },
|
||||||
0.,
|
0.,
|
||||||
1.,
|
1.,
|
||||||
st::toastFadeInDuration);
|
_sliding ? _st->durationSlide : _st->durationFadeIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDefaultParent(not_null<QWidget*> parent) {
|
void SetDefaultParent(not_null<QWidget*> parent) {
|
||||||
DefaultParent = parent;
|
DefaultParent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Show(not_null<QWidget*> parent, const Config &config) {
|
base::weak_ptr<Instance> Show(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
const Config &config) {
|
||||||
const auto manager = internal::Manager::instance(parent);
|
const auto manager = internal::Manager::instance(parent);
|
||||||
manager->addToast(std::make_unique<Instance>(
|
return manager->addToast(std::make_unique<Instance>(
|
||||||
config,
|
config,
|
||||||
parent,
|
parent,
|
||||||
Instance::Private()));
|
Instance::Private()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Show(const Config &config) {
|
base::weak_ptr<Instance> Show(const Config &config) {
|
||||||
if (const auto parent = DefaultParent.data()) {
|
if (const auto parent = DefaultParent.data()) {
|
||||||
Show(parent, config);
|
return Show(parent, config);
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Show(not_null<QWidget*> parent, const QString &text) {
|
base::weak_ptr<Instance> Show(
|
||||||
auto config = Config();
|
not_null<QWidget*> parent,
|
||||||
config.text = { text };
|
const QString &text) {
|
||||||
Show(parent, config);
|
return Show(parent, Config{ .text = { text }, .st = &st::defaultToast });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Show(const QString &text) {
|
base::weak_ptr<Instance> Show(const QString &text) {
|
||||||
auto config = Config();
|
return Show(Config{ .text = { text }, .st = &st::defaultToast });
|
||||||
config.text = { text };
|
|
||||||
Show(config);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::opacityAnimationCallback() {
|
void Instance::shownAnimationCallback() {
|
||||||
_widget->setShownLevel(_a_opacity.value(_hiding ? 0. : 1.));
|
_widget->setShownLevel(_shownAnimation.value(_hiding ? 0. : 1.));
|
||||||
_widget->update();
|
if (!_shownAnimation.animating()) {
|
||||||
if (!_a_opacity.animating()) {
|
|
||||||
if (_hiding) {
|
if (_hiding) {
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +75,11 @@ void Instance::opacityAnimationCallback() {
|
||||||
|
|
||||||
void Instance::hideAnimated() {
|
void Instance::hideAnimated() {
|
||||||
_hiding = true;
|
_hiding = true;
|
||||||
_a_opacity.start([this] { opacityAnimationCallback(); }, 1., 0., st::toastFadeOutDuration);
|
_shownAnimation.start(
|
||||||
|
[=] { shownAnimationCallback(); },
|
||||||
|
1.,
|
||||||
|
0.,
|
||||||
|
_sliding ? _st->durationSlide : _st->durationFadeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::hide() {
|
void Instance::hide() {
|
||||||
|
|
@ -80,5 +87,9 @@ void Instance::hide() {
|
||||||
_widget->deleteLater();
|
_widget->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
not_null<RpWidget*> Instance::widget() const {
|
||||||
|
return _widget.get();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Toast
|
} // namespace Toast
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,13 @@
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/text/text_entity.h"
|
#include "ui/text/text_entity.h"
|
||||||
#include "ui/click_handler.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;
|
||||||
|
} // namespace style
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Toast {
|
namespace Toast {
|
||||||
|
|
@ -23,22 +30,18 @@ using ClickHandlerFilter = Fn<bool(const ClickHandlerPtr&, Qt::MouseButton)>;
|
||||||
inline constexpr auto kDefaultDuration = crl::time(1500);
|
inline constexpr auto kDefaultDuration = crl::time(1500);
|
||||||
struct Config {
|
struct Config {
|
||||||
TextWithEntities text;
|
TextWithEntities text;
|
||||||
QMargins padding;
|
not_null<const style::Toast*> st;
|
||||||
crl::time durationMs = kDefaultDuration;
|
crl::time durationMs = kDefaultDuration;
|
||||||
int minWidth = 0;
|
|
||||||
int maxWidth = 0;
|
|
||||||
int maxLines = 16;
|
int maxLines = 16;
|
||||||
bool multiline = false;
|
bool multiline = false;
|
||||||
bool dark = false;
|
bool dark = false;
|
||||||
|
RectPart slideSide = RectPart::None;
|
||||||
ClickHandlerFilter filter;
|
ClickHandlerFilter filter;
|
||||||
};
|
};
|
||||||
void SetDefaultParent(not_null<QWidget*> parent);
|
|
||||||
void Show(not_null<QWidget*> parent, const Config &config);
|
|
||||||
void Show(const Config &config);
|
|
||||||
void Show(not_null<QWidget*> parent, const QString &text);
|
|
||||||
void Show(const QString &text);
|
|
||||||
|
|
||||||
class Instance {
|
void SetDefaultParent(not_null<QWidget*> parent);
|
||||||
|
|
||||||
|
class Instance final : public base::has_weak_ptr {
|
||||||
struct Private {
|
struct Private {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,20 +56,35 @@ public:
|
||||||
void hideAnimated();
|
void hideAnimated();
|
||||||
void hide();
|
void hide();
|
||||||
|
|
||||||
|
[[nodiscard]] not_null<RpWidget*> widget() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void opacityAnimationCallback();
|
void shownAnimationCallback();
|
||||||
|
|
||||||
|
const not_null<const style::Toast*> _st;
|
||||||
|
const crl::time _hideAt = 0;
|
||||||
|
|
||||||
|
Ui::Animations::Simple _shownAnimation;
|
||||||
bool _hiding = false;
|
bool _hiding = false;
|
||||||
Ui::Animations::Simple _a_opacity;
|
bool _sliding = false;
|
||||||
|
|
||||||
const crl::time _hideAtMs;
|
|
||||||
|
|
||||||
// ToastManager should reset _widget pointer if _widget is destroyed.
|
// ToastManager should reset _widget pointer if _widget is destroyed.
|
||||||
friend class internal::Manager;
|
friend class internal::Manager;
|
||||||
friend void Show(not_null<QWidget*> parent, const Config &config);
|
friend base::weak_ptr<Instance> Show(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
const Config &config);
|
||||||
std::unique_ptr<internal::Widget> _widget;
|
std::unique_ptr<internal::Widget> _widget;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
base::weak_ptr<Instance> Show(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
const Config &config);
|
||||||
|
base::weak_ptr<Instance> Show(const Config &config);
|
||||||
|
base::weak_ptr<Instance> Show(
|
||||||
|
not_null<QWidget*> parent,
|
||||||
|
const QString &text);
|
||||||
|
base::weak_ptr<Instance> Show(const QString &text);
|
||||||
|
|
||||||
} // namespace Toast
|
} // namespace Toast
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -44,13 +44,16 @@ not_null<Manager*> Manager::instance(not_null<QWidget*> parent) {
|
||||||
return i->second;
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::addToast(std::unique_ptr<Instance> &&toast) {
|
base::weak_ptr<Instance> Manager::addToast(
|
||||||
|
std::unique_ptr<Instance> &&toast) {
|
||||||
_toasts.push_back(std::move(toast));
|
_toasts.push_back(std::move(toast));
|
||||||
const auto t = _toasts.back().get();
|
const auto t = _toasts.back().get();
|
||||||
const auto widget = t->_widget.get();
|
const auto widget = t->_widget.get();
|
||||||
|
|
||||||
_toastByWidget.emplace(widget, t);
|
_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()) {
|
if (const auto parent = widget->parentWidget()) {
|
||||||
auto found = false;
|
auto found = false;
|
||||||
for (auto i = _toastParents.begin(); i != _toastParents.cend();) {
|
for (auto i = _toastParents.begin(); i != _toastParents.cend();) {
|
||||||
|
|
@ -72,10 +75,11 @@ void Manager::addToast(std::unique_ptr<Instance> &&toast) {
|
||||||
const auto nearestHide = _toastByHideTime.empty()
|
const auto nearestHide = _toastByHideTime.empty()
|
||||||
? 0LL
|
? 0LL
|
||||||
: _toastByHideTime.begin()->first;
|
: _toastByHideTime.begin()->first;
|
||||||
_toastByHideTime.emplace(t->_hideAtMs, t);
|
_toastByHideTime.emplace(t->_hideAt, t);
|
||||||
if (!nearestHide || _toastByHideTime.begin()->first < nearestHide) {
|
if (!nearestHide || _toastByHideTime.begin()->first < nearestHide) {
|
||||||
startNextHideTimer();
|
startNextHideTimer();
|
||||||
}
|
}
|
||||||
|
return make_weak(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::hideByTimer() {
|
void Manager::hideByTimer() {
|
||||||
|
|
@ -92,7 +96,7 @@ void Manager::hideByTimer() {
|
||||||
startNextHideTimer();
|
startNextHideTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::onToastWidgetDestroyed(QObject *widget) {
|
void Manager::toastWidgetDestroyed(QObject *widget) {
|
||||||
const auto i = _toastByWidget.find(static_cast<Widget*>(widget));
|
const auto i = _toastByWidget.find(static_cast<Widget*>(widget));
|
||||||
if (i == _toastByWidget.cend()) {
|
if (i == _toastByWidget.cend()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -101,6 +105,13 @@ void Manager::onToastWidgetDestroyed(QObject *widget) {
|
||||||
_toastByWidget.erase(i);
|
_toastByWidget.erase(i);
|
||||||
toast->_widget.release();
|
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(
|
const auto j = ranges::find(
|
||||||
_toasts,
|
_toasts,
|
||||||
toast.get(),
|
toast.get(),
|
||||||
|
|
@ -111,7 +122,9 @@ void Manager::onToastWidgetDestroyed(QObject *widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::startNextHideTimer() {
|
void Manager::startNextHideTimer() {
|
||||||
if (_toastByHideTime.empty()) return;
|
if (_toastByHideTime.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto ms = crl::now();
|
auto ms = crl::now();
|
||||||
if (ms >= _toastByHideTime.begin()->first) {
|
if (ms >= _toastByHideTime.begin()->first) {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ namespace Toast {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class Widget;
|
class Widget;
|
||||||
class Manager : public QObject {
|
class Manager final : public QObject {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
struct CreateTag {
|
struct CreateTag {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -28,20 +26,17 @@ public:
|
||||||
|
|
||||||
static not_null<Manager*> instance(not_null<QWidget*> parent);
|
static not_null<Manager*> instance(not_null<QWidget*> parent);
|
||||||
|
|
||||||
void addToast(std::unique_ptr<Instance> &&toast);
|
base::weak_ptr<Instance> addToast(std::unique_ptr<Instance> &&toast);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *o, QEvent *e);
|
bool eventFilter(QObject *o, QEvent *e);
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onToastWidgetDestroyed(QObject *widget);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void toastWidgetDestroyed(QObject *widget);
|
||||||
void startNextHideTimer();
|
void startNextHideTimer();
|
||||||
void hideByTimer();
|
void hideByTimer();
|
||||||
|
|
||||||
base::Timer _hideTimer;
|
base::Timer _hideTimer;
|
||||||
crl::time _nextHide = 0;
|
|
||||||
|
|
||||||
base::flat_multi_map<crl::time, not_null<Instance*>> _toastByHideTime;
|
base::flat_multi_map<crl::time, not_null<Instance*>> _toastByHideTime;
|
||||||
base::flat_map<not_null<Widget*>, not_null<Instance*>> _toastByWidget;
|
base::flat_map<not_null<Widget*>, not_null<Instance*>> _toastByWidget;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "ui/image/image_prepare.h"
|
#include "ui/image/image_prepare.h"
|
||||||
#include "styles/palette.h"
|
#include "styles/palette.h"
|
||||||
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
#include <QtGui/QtEvents>
|
#include <QtGui/QtEvents>
|
||||||
|
|
||||||
|
|
@ -16,16 +17,16 @@ namespace Toast {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent, const Config &config)
|
Widget::Widget(QWidget *parent, const Config &config)
|
||||||
: TWidget(parent)
|
: RpWidget(parent)
|
||||||
|
, _st(config.st)
|
||||||
, _roundRect(ImageRoundRadius::Large, st::toastBg)
|
, _roundRect(ImageRoundRadius::Large, st::toastBg)
|
||||||
|
, _slideSide(config.slideSide)
|
||||||
, _multiline(config.multiline)
|
, _multiline(config.multiline)
|
||||||
, _dark(config.dark)
|
, _dark(config.dark)
|
||||||
, _maxWidth((config.maxWidth > 0) ? config.maxWidth : st::toastMaxWidth)
|
, _maxTextWidth(widthWithoutPadding(_st->maxWidth))
|
||||||
, _padding((config.padding.left() > 0) ? config.padding : st::toastPadding)
|
|
||||||
, _maxTextWidth(widthWithoutPadding(_maxWidth))
|
|
||||||
, _maxTextHeight(
|
, _maxTextHeight(
|
||||||
st::toastTextStyle.font->height * (_multiline ? config.maxLines : 1))
|
config.st->style.font->height * (_multiline ? config.maxLines : 1))
|
||||||
, _text(_multiline ? widthWithoutPadding(config.minWidth) : QFIXED_MAX)
|
, _text(_multiline ? widthWithoutPadding(config.st->minWidth) : QFIXED_MAX)
|
||||||
, _clickHandlerFilter(config.filter) {
|
, _clickHandlerFilter(config.filter) {
|
||||||
const auto toastOptions = TextParseOptions{
|
const auto toastOptions = TextParseOptions{
|
||||||
TextParseMultiline,
|
TextParseMultiline,
|
||||||
|
|
@ -34,7 +35,7 @@ Widget::Widget(QWidget *parent, const Config &config)
|
||||||
Qt::LayoutDirectionAuto
|
Qt::LayoutDirectionAuto
|
||||||
};
|
};
|
||||||
_text.setMarkedText(
|
_text.setMarkedText(
|
||||||
st::toastTextStyle,
|
_st->style,
|
||||||
_multiline ? config.text : TextUtilities::SingleLine(config.text),
|
_multiline ? config.text : TextUtilities::SingleLine(config.text),
|
||||||
toastOptions);
|
toastOptions);
|
||||||
|
|
||||||
|
|
@ -49,36 +50,102 @@ Widget::Widget(QWidget *parent, const Config &config)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::onParentResized() {
|
void Widget::onParentResized() {
|
||||||
auto newWidth = _maxWidth;
|
updateGeometry();
|
||||||
accumulate_min(newWidth, _padding.left() + _text.maxWidth() + _padding.right());
|
}
|
||||||
accumulate_min(newWidth, parentWidget()->width() - 2 * st::toastMinMargin);
|
|
||||||
_textWidth = widthWithoutPadding(newWidth);
|
void Widget::updateGeometry() {
|
||||||
const auto textHeight = _multiline
|
auto width = _st->maxWidth;
|
||||||
|
accumulate_min(
|
||||||
|
width,
|
||||||
|
_st->padding.left() + _text.maxWidth() + _st->padding.right());
|
||||||
|
accumulate_min(
|
||||||
|
width,
|
||||||
|
parentWidget()->width() - _st->margin.left() - _st->margin.right());
|
||||||
|
_textWidth = widthWithoutPadding(width);
|
||||||
|
_textHeight = _multiline
|
||||||
? qMin(_text.countHeight(_textWidth), _maxTextHeight)
|
? qMin(_text.countHeight(_textWidth), _maxTextHeight)
|
||||||
: _text.minHeight();
|
: _text.minHeight();
|
||||||
const auto newHeight = _padding.top() + textHeight + _padding.bottom();
|
const auto minHeight = _st->icon.empty()
|
||||||
setGeometry((parentWidget()->width() - newWidth) / 2, (parentWidget()->height() - newHeight) / 2, newWidth, newHeight);
|
? 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());
|
||||||
|
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) {
|
void Widget::setShownLevel(float64 shownLevel) {
|
||||||
_shownLevel = shownLevel;
|
_shownLevel = shownLevel;
|
||||||
|
if (_slideSide != RectPart::None) {
|
||||||
|
updateGeometry();
|
||||||
|
} else {
|
||||||
|
update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::paintEvent(QPaintEvent *e) {
|
void Widget::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
|
|
||||||
p.setOpacity(_shownLevel);
|
if (_slideSide == RectPart::None) {
|
||||||
|
p.setOpacity(_shownLevel);
|
||||||
|
}
|
||||||
_roundRect.paint(p, rect());
|
_roundRect.paint(p, rect());
|
||||||
if (_dark) {
|
if (_dark) {
|
||||||
_roundRect.paint(p, rect());
|
_roundRect.paint(p, rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
p.setTextPalette(st::toastTextPalette);
|
if (!_st->icon.empty()) {
|
||||||
|
_st->icon.paint(
|
||||||
|
p,
|
||||||
|
_st->iconPosition.x(),
|
||||||
|
_st->iconPosition.y(),
|
||||||
|
width());
|
||||||
|
}
|
||||||
|
|
||||||
const auto lines = _maxTextHeight / st::toastTextStyle.font->height;
|
p.setTextPalette(_st->palette);
|
||||||
|
|
||||||
|
const auto lines = _maxTextHeight / _st->style.font->height;
|
||||||
p.setPen(st::toastFg);
|
p.setPen(st::toastFg);
|
||||||
_text.drawElided(p, _padding.left(), _padding.top(), _textWidth + 1, lines);
|
_text.drawElided(
|
||||||
|
p,
|
||||||
|
_st->padding.left(),
|
||||||
|
_textTop,
|
||||||
|
_textWidth + 1,
|
||||||
|
lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::leaveEventHook(QEvent *e) {
|
void Widget::leaveEventHook(QEvent *e) {
|
||||||
|
|
@ -96,8 +163,9 @@ void Widget::mouseMoveEvent(QMouseEvent *e) {
|
||||||
if (!_text.hasLinks()) {
|
if (!_text.hasLinks()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto point = e->pos() - QPoint(_padding.left(), _padding.top());
|
const auto point = e->pos()
|
||||||
const auto lines = _maxTextHeight / st::toastTextStyle.font->height;
|
- QPoint(_st->padding.left(), _textTop);
|
||||||
|
const auto lines = _maxTextHeight / _st->style.font->height;
|
||||||
const auto state = _text.getStateElided(point, _textWidth + 1);
|
const auto state = _text.getStateElided(point, _textWidth + 1);
|
||||||
const auto was = ClickHandler::getActive();
|
const auto was = ClickHandler::getActive();
|
||||||
if (was != state.link) {
|
if (was != state.link) {
|
||||||
|
|
@ -129,6 +197,10 @@ void Widget::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Widget::widthWithoutPadding(int w) const {
|
||||||
|
return w - _st->padding.left() - _st->padding.right();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace Toast
|
} // namespace Toast
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Ui {
|
||||||
namespace Toast {
|
namespace Toast {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class Widget : public TWidget {
|
class Widget final : public RpWidget {
|
||||||
public:
|
public:
|
||||||
Widget(QWidget *parent, const Config &config);
|
Widget(QWidget *parent, const Config &config);
|
||||||
|
|
||||||
|
|
@ -33,21 +33,22 @@ protected:
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int widthWithoutPadding(int w) {
|
[[nodiscard]] int widthWithoutPadding(int w) const;
|
||||||
return w - _padding.left() - _padding.right();
|
void updateGeometry();
|
||||||
}
|
|
||||||
|
|
||||||
|
const not_null<const style::Toast*> _st;
|
||||||
RoundRect _roundRect;
|
RoundRect _roundRect;
|
||||||
|
RectPart _slideSide = RectPart::None;
|
||||||
|
|
||||||
float64 _shownLevel = 0;
|
float64 _shownLevel = 0;
|
||||||
bool _multiline = false;
|
bool _multiline = false;
|
||||||
bool _dark = false;
|
bool _dark = false;
|
||||||
int _maxWidth = 0;
|
|
||||||
QMargins _padding;
|
|
||||||
|
|
||||||
int _maxTextWidth = 0;
|
int _maxTextWidth = 0;
|
||||||
int _maxTextHeight = 0;
|
int _maxTextHeight = 0;
|
||||||
int _textWidth = 0;
|
int _textWidth = 0;
|
||||||
|
int _textHeight = 0;
|
||||||
|
int _textTop = 0;
|
||||||
Text::String _text;
|
Text::String _text;
|
||||||
|
|
||||||
ClickHandlerFilter _clickHandlerFilter;
|
ClickHandlerFilter _clickHandlerFilter;
|
||||||
|
|
|
||||||
|
|
@ -568,6 +568,20 @@ SideBarButton {
|
||||||
ripple: RippleAnimation;
|
ripple: RippleAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Toast {
|
||||||
|
style: TextStyle;
|
||||||
|
icon: icon;
|
||||||
|
iconPosition: point;
|
||||||
|
palette: TextPalette;
|
||||||
|
padding: margins;
|
||||||
|
margin: margins;
|
||||||
|
minWidth: pixels;
|
||||||
|
maxWidth: pixels;
|
||||||
|
durationFadeIn: int;
|
||||||
|
durationFadeOut: int;
|
||||||
|
durationSlide: int;
|
||||||
|
}
|
||||||
|
|
||||||
defaultLabelSimple: LabelSimple {
|
defaultLabelSimple: LabelSimple {
|
||||||
font: normalFont;
|
font: normalFont;
|
||||||
maxWidth: 0px;
|
maxWidth: 0px;
|
||||||
|
|
@ -1248,7 +1262,7 @@ defaultSettingsButton: SettingsButton {
|
||||||
|
|
||||||
toggle: defaultSettingsToggle;
|
toggle: defaultSettingsToggle;
|
||||||
toggleOver: defaultSettingsToggleOver;
|
toggleOver: defaultSettingsToggleOver;
|
||||||
toggleSkip: 23px;
|
toggleSkip: 22px;
|
||||||
|
|
||||||
ripple: defaultRippleAnimation;
|
ripple: defaultRippleAnimation;
|
||||||
}
|
}
|
||||||
|
|
@ -1266,6 +1280,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: 160;
|
||||||
|
}
|
||||||
|
|
||||||
// Windows specific title
|
// Windows specific title
|
||||||
|
|
||||||
windowTitleButton: IconButton {
|
windowTitleButton: IconButton {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue