2017-10-08 16:49:56 +03:00
|
|
|
#include <QPainter>
|
|
|
|
|
2018-07-04 01:38:54 +03:00
|
|
|
#include <tweeny/tweeny.h>
|
2018-03-16 18:56:45 +03:00
|
|
|
|
2017-10-08 16:49:56 +03:00
|
|
|
#include "SnackBar.h"
|
|
|
|
|
2018-07-25 23:07:56 +03:00
|
|
|
constexpr int STARTING_OFFSET = 1;
|
|
|
|
constexpr int ANIMATION_DURATION = 6'000;
|
|
|
|
constexpr int BOX_PADDING = 10;
|
|
|
|
constexpr double MIN_WIDTH = 400.0;
|
|
|
|
constexpr double MIN_WIDTH_PERCENTAGE = 0.3;
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
SnackBar::SnackBar(QWidget *parent)
|
|
|
|
: OverlayWidget(parent)
|
|
|
|
{
|
2018-07-25 23:07:56 +03:00
|
|
|
QFont font;
|
|
|
|
font.setPointSizeF(font.pointSizeF() * 1.2);
|
2017-12-11 00:59:50 +03:00
|
|
|
font.setWeight(50);
|
2017-10-08 16:49:56 +03:00
|
|
|
setFont(font);
|
|
|
|
|
2018-07-25 23:07:56 +03:00
|
|
|
boxHeight_ = QFontMetrics(font).height() * 2;
|
|
|
|
offset_ = STARTING_OFFSET;
|
|
|
|
position_ = SnackBarPosition::Top;
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
hideTimer_.setSingleShot(true);
|
2017-10-08 16:49:56 +03:00
|
|
|
|
2018-03-17 12:38:06 +03:00
|
|
|
auto offset_anim = tweeny::from(1.0f).to(0.0f).during(100).via(tweeny::easing::cubicOut);
|
2018-05-08 23:38:57 +03:00
|
|
|
connect(&showTimer_, &QTimer::timeout, this, [this, offset_anim]() mutable {
|
2018-03-16 18:56:45 +03:00
|
|
|
if (offset_anim.progress() < 1.0f) {
|
2018-03-17 12:38:06 +03:00
|
|
|
offset_ = offset_anim.step(0.07f);
|
2018-07-25 23:07:56 +03:00
|
|
|
repaint();
|
2018-03-16 18:56:45 +03:00
|
|
|
} else {
|
2018-05-08 23:38:57 +03:00
|
|
|
showTimer_.stop();
|
2018-07-25 23:07:56 +03:00
|
|
|
hideTimer_.start(ANIMATION_DURATION);
|
2018-03-16 18:56:45 +03:00
|
|
|
offset_anim.seek(0.0f);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
|
|
|
|
|
|
|
|
hide();
|
2017-10-08 16:49:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::start()
|
|
|
|
{
|
2018-05-08 23:38:57 +03:00
|
|
|
if (messages_.empty())
|
|
|
|
return;
|
|
|
|
|
2017-10-08 16:49:56 +03:00
|
|
|
show();
|
|
|
|
raise();
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
showTimer_.start(10);
|
2017-10-08 16:49:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::hideMessage()
|
|
|
|
{
|
|
|
|
stopTimers();
|
|
|
|
hide();
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
if (!messages_.empty())
|
|
|
|
// Moving on to the next message.
|
|
|
|
messages_.pop_front();
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
// Reseting the starting position of the widget.
|
|
|
|
offset_ = STARTING_OFFSET;
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
if (!messages_.empty())
|
2017-10-08 16:49:56 +03:00
|
|
|
start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::stopTimers()
|
|
|
|
{
|
2018-05-08 23:38:57 +03:00
|
|
|
showTimer_.stop();
|
|
|
|
hideTimer_.stop();
|
2017-10-08 16:49:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::showMessage(const QString &msg)
|
|
|
|
{
|
|
|
|
messages_.push_back(msg);
|
|
|
|
|
|
|
|
// There is already an active message.
|
|
|
|
if (isVisible())
|
|
|
|
return;
|
|
|
|
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::mousePressEvent(QMouseEvent *)
|
|
|
|
{
|
|
|
|
hideMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SnackBar::paintEvent(QPaintEvent *event)
|
|
|
|
{
|
|
|
|
Q_UNUSED(event)
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
if (messages_.empty())
|
2017-10-08 16:49:56 +03:00
|
|
|
return;
|
|
|
|
|
2018-05-08 23:38:57 +03:00
|
|
|
auto message_ = messages_.front();
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
QPainter p(this);
|
|
|
|
p.setRenderHint(QPainter::Antialiasing);
|
|
|
|
|
|
|
|
QBrush brush;
|
|
|
|
brush.setStyle(Qt::SolidPattern);
|
|
|
|
brush.setColor(bgColor_);
|
|
|
|
p.setBrush(brush);
|
|
|
|
|
2018-07-25 23:07:56 +03:00
|
|
|
QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
p.setPen(Qt::white);
|
|
|
|
QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
|
|
|
|
|
|
|
p.setPen(Qt::NoPen);
|
2018-07-25 23:07:56 +03:00
|
|
|
r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
const qreal s = 1 - offset_;
|
|
|
|
|
|
|
|
if (position_ == SnackBarPosition::Bottom)
|
2018-07-25 23:07:56 +03:00
|
|
|
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
|
|
|
height() - BOX_PADDING - s * (r.height()));
|
2017-10-08 16:49:56 +03:00
|
|
|
else
|
2018-07-25 23:07:56 +03:00
|
|
|
p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
|
|
|
|
s * (r.height()) - 2 * BOX_PADDING);
|
2017-10-08 16:49:56 +03:00
|
|
|
|
|
|
|
br.moveCenter(r.center());
|
2018-07-25 23:07:56 +03:00
|
|
|
p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
|
2017-10-08 16:49:56 +03:00
|
|
|
p.setPen(textColor_);
|
|
|
|
p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
|
|
|
|
}
|