mirror of https://github.com/Nheko-Reborn/nheko
parent
ebe36b5713
commit
ac525970b0
@ -0,0 +1,80 @@ |
||||
#pragma once |
||||
|
||||
#include <QCoreApplication> |
||||
#include <QPaintEvent> |
||||
#include <QStateMachine> |
||||
#include <QTimer> |
||||
|
||||
#include "OverlayWidget.h" |
||||
|
||||
enum class SnackBarPosition { |
||||
Bottom, |
||||
Top, |
||||
}; |
||||
|
||||
class SnackBar : public OverlayWidget |
||||
{ |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
explicit SnackBar(QWidget *parent); |
||||
~SnackBar(); |
||||
|
||||
inline void setBackgroundColor(const QColor &color); |
||||
inline void setTextColor(const QColor &color); |
||||
inline void setPosition(SnackBarPosition pos); |
||||
|
||||
public slots: |
||||
void showMessage(const QString &msg); |
||||
|
||||
protected: |
||||
void paintEvent(QPaintEvent *event) override; |
||||
void mousePressEvent(QMouseEvent *event) override; |
||||
|
||||
private slots: |
||||
void onTimeout(); |
||||
void hideMessage(); |
||||
|
||||
private: |
||||
void stopTimers(); |
||||
void start(); |
||||
|
||||
QColor bgColor_; |
||||
QColor textColor_; |
||||
|
||||
qreal bgOpacity_; |
||||
qreal offset_; |
||||
|
||||
QList<QString> messages_; |
||||
|
||||
QTimer *showTimer_; |
||||
QTimer *hideTimer_; |
||||
|
||||
int duration_; |
||||
int boxWidth_; |
||||
int boxHeight_; |
||||
int boxPadding_; |
||||
|
||||
SnackBarPosition position_; |
||||
}; |
||||
|
||||
inline void |
||||
SnackBar::setPosition(SnackBarPosition pos) |
||||
{ |
||||
position_ = pos; |
||||
update(); |
||||
} |
||||
|
||||
inline void |
||||
SnackBar::setBackgroundColor(const QColor &color) |
||||
{ |
||||
bgColor_ = color; |
||||
update(); |
||||
} |
||||
|
||||
inline void |
||||
SnackBar::setTextColor(const QColor &color) |
||||
{ |
||||
textColor_ = color; |
||||
update(); |
||||
} |
@ -0,0 +1,143 @@ |
||||
#include <QDebug> |
||||
#include <QPainter> |
||||
|
||||
#include "SnackBar.h" |
||||
|
||||
constexpr int STARTING_OFFSET = 1; |
||||
|
||||
SnackBar::SnackBar(QWidget *parent) |
||||
: OverlayWidget(parent) |
||||
{ |
||||
bgOpacity_ = 0.9; |
||||
duration_ = 6000; |
||||
boxWidth_ = 400; |
||||
boxHeight_ = 40; |
||||
boxPadding_ = 10; |
||||
textColor_ = QColor("white"); |
||||
bgColor_ = QColor("#333"); |
||||
offset_ = STARTING_OFFSET; |
||||
position_ = SnackBarPosition::Top; |
||||
|
||||
QFont font("Open Sans", 14, QFont::Medium); |
||||
setFont(font); |
||||
|
||||
showTimer_ = new QTimer(); |
||||
hideTimer_ = new QTimer(); |
||||
hideTimer_->setSingleShot(true); |
||||
|
||||
connect(showTimer_, SIGNAL(timeout()), this, SLOT(onTimeout())); |
||||
connect(hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage())); |
||||
} |
||||
|
||||
SnackBar::~SnackBar() |
||||
{ |
||||
stopTimers(); |
||||
|
||||
delete showTimer_; |
||||
delete hideTimer_; |
||||
} |
||||
|
||||
void |
||||
SnackBar::start() |
||||
{ |
||||
show(); |
||||
raise(); |
||||
|
||||
showTimer_->start(10); |
||||
} |
||||
|
||||
void |
||||
SnackBar::hideMessage() |
||||
{ |
||||
stopTimers(); |
||||
hide(); |
||||
|
||||
// Moving on to the next message.
|
||||
messages_.removeFirst(); |
||||
|
||||
// Reseting the starting position of the widget.
|
||||
offset_ = STARTING_OFFSET; |
||||
|
||||
if (!messages_.isEmpty()) |
||||
start(); |
||||
} |
||||
|
||||
void |
||||
SnackBar::stopTimers() |
||||
{ |
||||
showTimer_->stop(); |
||||
hideTimer_->stop(); |
||||
} |
||||
|
||||
void |
||||
SnackBar::showMessage(const QString &msg) |
||||
{ |
||||
messages_.push_back(msg); |
||||
|
||||
// There is already an active message.
|
||||
if (isVisible()) |
||||
return; |
||||
|
||||
start(); |
||||
} |
||||
|
||||
void |
||||
SnackBar::onTimeout() |
||||
{ |
||||
offset_ -= 0.5; |
||||
|
||||
if (offset_ <= 0.0) { |
||||
showTimer_->stop(); |
||||
hideTimer_->start(duration_); |
||||
} |
||||
|
||||
update(); |
||||
} |
||||
|
||||
void |
||||
SnackBar::mousePressEvent(QMouseEvent *) |
||||
{ |
||||
hideMessage(); |
||||
} |
||||
|
||||
void |
||||
SnackBar::paintEvent(QPaintEvent *event) |
||||
{ |
||||
Q_UNUSED(event) |
||||
|
||||
if (messages_.isEmpty()) |
||||
return; |
||||
|
||||
auto message_ = messages_.first(); |
||||
|
||||
QPainter p(this); |
||||
p.setRenderHint(QPainter::Antialiasing); |
||||
|
||||
QBrush brush; |
||||
brush.setStyle(Qt::SolidPattern); |
||||
brush.setColor(bgColor_); |
||||
p.setBrush(brush); |
||||
p.setOpacity(bgOpacity_); |
||||
|
||||
QRect r(0, 0, boxWidth_, boxHeight_); |
||||
|
||||
p.setPen(Qt::white); |
||||
QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_); |
||||
|
||||
p.setPen(Qt::NoPen); |
||||
r = br.united(r).adjusted(-boxPadding_, -boxPadding_, boxPadding_, boxPadding_); |
||||
|
||||
const qreal s = 1 - offset_; |
||||
|
||||
if (position_ == SnackBarPosition::Bottom) |
||||
p.translate((width() - (r.width() - 2 * boxPadding_)) / 2, |
||||
height() - boxPadding_ - s * (r.height())); |
||||
else |
||||
p.translate((width() - (r.width() - 2 * boxPadding_)) / 2, |
||||
s * (r.height()) - 2 * boxPadding_); |
||||
|
||||
br.moveCenter(r.center()); |
||||
p.drawRoundedRect(r.adjusted(0, 0, 0, 3), 3, 3); |
||||
p.setPen(textColor_); |
||||
p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_); |
||||
} |
Loading…
Reference in new issue