Add Snackbar files
This commit is contained in:
parent
231f01b5a6
commit
5a7d6ee7a1
|
@ -0,0 +1,267 @@
|
|||
#include "xx/qtmaterialsnackbar.h"
|
||||
#include "xx/qtmaterialsnackbar_p.h"
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QFontDatabase>
|
||||
#include "xx/qtmaterialsnackbar_internal.h"
|
||||
#include "xxlib/qtmaterialstyle.h"
|
||||
#include "xxlib/qtmaterialstatetransition.h"
|
||||
#include <QDebug>
|
||||
|
||||
/*!
|
||||
* \class QtMaterialSnackbarPrivate
|
||||
* \internal
|
||||
*/
|
||||
|
||||
QtMaterialSnackbarPrivate::QtMaterialSnackbarPrivate(QtMaterialSnackbar *q)
|
||||
: q_ptr(q)
|
||||
{
|
||||
}
|
||||
|
||||
QtMaterialSnackbarPrivate::~QtMaterialSnackbarPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
void QtMaterialSnackbarPrivate::init()
|
||||
{
|
||||
Q_Q(QtMaterialSnackbar);
|
||||
|
||||
stateMachine = new QtMaterialSnackbarStateMachine(q);
|
||||
bgOpacity = 0.9;
|
||||
duration = 3000;
|
||||
boxWidth = 300;
|
||||
clickDismiss = false;
|
||||
useThemeColors = true;
|
||||
|
||||
q->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
QFontDatabase db;
|
||||
QFont font(db.font("Roboto", "Medium", 10));
|
||||
font.setCapitalization(QFont::AllUppercase);
|
||||
q->setFont(font);
|
||||
|
||||
stateMachine->start();
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \class QtMaterialSnackbar
|
||||
*/
|
||||
|
||||
QtMaterialSnackbar::QtMaterialSnackbar(QWidget *parent)
|
||||
: QtMaterialOverlayWidget(parent),
|
||||
d_ptr(new QtMaterialSnackbarPrivate(this))
|
||||
{
|
||||
d_func()->init();
|
||||
}
|
||||
|
||||
QtMaterialSnackbar::~QtMaterialSnackbar()
|
||||
{
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setAutoHideDuration(int duration)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->duration = duration;
|
||||
}
|
||||
|
||||
int QtMaterialSnackbar::autoHideDuration() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
return d->duration;
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setUseThemeColors(bool value)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
if (d->useThemeColors == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->useThemeColors = value;
|
||||
update();
|
||||
}
|
||||
|
||||
bool QtMaterialSnackbar::useThemeColors() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
return d->useThemeColors;
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setBackgroundColor(const QColor &color)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->backgroundColor = color;
|
||||
setUseThemeColors(false);
|
||||
}
|
||||
|
||||
QColor QtMaterialSnackbar::backgroundColor() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
if (d->useThemeColors || !d->backgroundColor.isValid()) {
|
||||
return QtMaterialStyle::instance().themeColor("text");
|
||||
} else {
|
||||
return d->backgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setBackgroundOpacity(qreal opacity)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->bgOpacity = opacity;
|
||||
update();
|
||||
}
|
||||
|
||||
qreal QtMaterialSnackbar::backgroundOpacity() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
return d->bgOpacity;
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setTextColor(const QColor &color)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->textColor = color;
|
||||
setUseThemeColors(false);
|
||||
}
|
||||
|
||||
QColor QtMaterialSnackbar::textColor() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
if (d->useThemeColors || !d->textColor.isValid()) {
|
||||
return QtMaterialStyle::instance().themeColor("canvas");
|
||||
} else {
|
||||
return d->textColor;
|
||||
}
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setFontSize(qreal size)
|
||||
{
|
||||
QFont f(font());
|
||||
f.setPointSizeF(size);
|
||||
setFont(f);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
qreal QtMaterialSnackbar::fontSize() const
|
||||
{
|
||||
return font().pointSizeF();
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setBoxWidth(int width)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->boxWidth = width;
|
||||
update();
|
||||
}
|
||||
|
||||
int QtMaterialSnackbar::boxWidth() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
return d->boxWidth;
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::setClickToDismissMode(bool value)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->clickDismiss = value;
|
||||
}
|
||||
|
||||
bool QtMaterialSnackbar::clickToDismissMode() const
|
||||
{
|
||||
Q_D(const QtMaterialSnackbar);
|
||||
|
||||
return d->clickDismiss;
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::addMessage(const QString &message)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
d->messages.push_back(message);
|
||||
d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SnackbarShowTransition));
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::addInstantMessage(const QString &message)
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
if (d->messages.isEmpty()) {
|
||||
d->messages.push_back(message);
|
||||
} else {
|
||||
d->messages.insert(1, message);
|
||||
}
|
||||
|
||||
d->stateMachine->progress();
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::dequeue()
|
||||
{
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
if (d->messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
d->messages.removeFirst();
|
||||
|
||||
if (!d->messages.isEmpty()) {
|
||||
d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SnackbarNextTransition));
|
||||
} else {
|
||||
d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SnackbarWaitTransition));
|
||||
}
|
||||
}
|
||||
|
||||
void QtMaterialSnackbar::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
Q_D(QtMaterialSnackbar);
|
||||
|
||||
if (d->messages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString message = d->messages.first();
|
||||
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QBrush brush;
|
||||
brush.setStyle(Qt::SolidPattern);
|
||||
brush.setColor(backgroundColor());
|
||||
painter.setBrush(brush);
|
||||
painter.setOpacity(d->bgOpacity);
|
||||
|
||||
QRect r(0, 0, d->boxWidth, 40);
|
||||
|
||||
painter.setPen(Qt::white);
|
||||
QRect br = painter.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message);
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
r = br.united(r).adjusted(-10, -10, 10, 20);
|
||||
|
||||
const qreal s = 1-d->stateMachine->offset();
|
||||
|
||||
painter.translate((width()-(r.width()-20))/2,
|
||||
height()+10-s*(r.height()));
|
||||
|
||||
br.moveCenter(r.center());
|
||||
painter.drawRoundedRect(r.adjusted(0, 0, 0, 3), 3, 3);
|
||||
painter.setPen(textColor());
|
||||
painter.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef QTMATERIALSNACKBAR_H
|
||||
#define QTMATERIALSNACKBAR_H
|
||||
|
||||
#include "xxlib/qtmaterialoverlaywidget.h"
|
||||
|
||||
class QtMaterialSnackbarPrivate;
|
||||
|
||||
class QtMaterialSnackbar : public QtMaterialOverlayWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QtMaterialSnackbar(QWidget *parent = 0);
|
||||
~QtMaterialSnackbar();
|
||||
|
||||
void setAutoHideDuration(int duration);
|
||||
int autoHideDuration() const;
|
||||
|
||||
void setUseThemeColors(bool value);
|
||||
bool useThemeColors() const;
|
||||
|
||||
void setBackgroundColor(const QColor &color);
|
||||
QColor backgroundColor() const;
|
||||
|
||||
void setBackgroundOpacity(qreal opacity);
|
||||
qreal backgroundOpacity() const;
|
||||
|
||||
void setTextColor(const QColor &color);
|
||||
QColor textColor() const;
|
||||
|
||||
void setFontSize(qreal size);
|
||||
qreal fontSize() const;
|
||||
|
||||
void setBoxWidth(int width);
|
||||
int boxWidth() const;
|
||||
|
||||
void setClickToDismissMode(bool value);
|
||||
bool clickToDismissMode() const;
|
||||
|
||||
public slots:
|
||||
void addMessage(const QString &message);
|
||||
void addInstantMessage(const QString &message);
|
||||
|
||||
protected slots:
|
||||
void dequeue();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
const QScopedPointer<QtMaterialSnackbarPrivate> d_ptr;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QtMaterialSnackbar)
|
||||
Q_DECLARE_PRIVATE(QtMaterialSnackbar)
|
||||
};
|
||||
|
||||
#endif // QTMATERIALSNACKBAR_H
|
|
@ -0,0 +1,99 @@
|
|||
#include "xx/qtmaterialsnackbar_internal.h"
|
||||
#include <QPropertyAnimation>
|
||||
#include "xx/qtmaterialsnackbar.h"
|
||||
#include "xxlib/qtmaterialstatetransition.h"
|
||||
#include <QDebug>
|
||||
|
||||
QtMaterialSnackbarStateMachine::QtMaterialSnackbarStateMachine(QtMaterialSnackbar *parent)
|
||||
: QStateMachine(parent),
|
||||
m_snackbar(parent)
|
||||
{
|
||||
m_timer.setSingleShot(true);
|
||||
|
||||
QState *hiddenState = new QState;
|
||||
QState *visibleState = new QState;
|
||||
QState *finalState = new QState;
|
||||
|
||||
addState(hiddenState);
|
||||
addState(visibleState);
|
||||
addState(finalState);
|
||||
|
||||
setInitialState(hiddenState);
|
||||
|
||||
QtMaterialStateTransition *transition;
|
||||
|
||||
transition = new QtMaterialStateTransition(SnackbarShowTransition);
|
||||
transition->setTargetState(visibleState);
|
||||
hiddenState->addTransition(transition);
|
||||
|
||||
transition = new QtMaterialStateTransition(SnackbarHideTransition);
|
||||
transition->setTargetState(visibleState);
|
||||
hiddenState->addTransition(transition);
|
||||
|
||||
transition = new QtMaterialStateTransition(SnackbarHideTransition);
|
||||
transition->setTargetState(finalState);
|
||||
visibleState->addTransition(transition);
|
||||
|
||||
transition = new QtMaterialStateTransition(SnackbarWaitTransition);
|
||||
transition->setTargetState(hiddenState);
|
||||
finalState->addTransition(transition);
|
||||
|
||||
transition = new QtMaterialStateTransition(SnackbarNextTransition);
|
||||
transition->setTargetState(visibleState);
|
||||
finalState->addTransition(transition);
|
||||
|
||||
connect(visibleState, SIGNAL(propertiesAssigned()),
|
||||
this, SLOT(snackbarShown()));
|
||||
connect(finalState, SIGNAL(propertiesAssigned()),
|
||||
m_snackbar, SLOT(dequeue()));
|
||||
|
||||
QPropertyAnimation *animation;
|
||||
|
||||
animation = new QPropertyAnimation(this, "offset", this);
|
||||
animation->setEasingCurve(QEasingCurve::OutCubic);
|
||||
animation->setDuration(400);
|
||||
addDefaultAnimation(animation);
|
||||
|
||||
hiddenState->assignProperty(this, "offset", 1);
|
||||
visibleState->assignProperty(this, "offset", 0);
|
||||
finalState->assignProperty(this, "offset", 1);
|
||||
|
||||
connect(&m_timer, SIGNAL(timeout()), this, SLOT(progress()));
|
||||
|
||||
m_snackbar->installEventFilter(this);
|
||||
}
|
||||
|
||||
QtMaterialSnackbarStateMachine::~QtMaterialSnackbarStateMachine()
|
||||
{
|
||||
}
|
||||
|
||||
bool QtMaterialSnackbarStateMachine::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (QEvent::MouseButtonPress == event->type() && m_snackbar->clickToDismissMode()) {
|
||||
progress();
|
||||
}
|
||||
return QStateMachine::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void QtMaterialSnackbarStateMachine::setOffset(qreal offset)
|
||||
{
|
||||
m_offset = offset;
|
||||
m_snackbar->update();
|
||||
}
|
||||
|
||||
void QtMaterialSnackbarStateMachine::progress()
|
||||
{
|
||||
m_timer.stop();
|
||||
postEvent(new QtMaterialStateTransitionEvent(SnackbarHideTransition));
|
||||
if (m_snackbar->clickToDismissMode()) {
|
||||
m_snackbar->setAttribute(Qt::WA_TransparentForMouseEvents, true);
|
||||
}
|
||||
}
|
||||
|
||||
void QtMaterialSnackbarStateMachine::snackbarShown()
|
||||
{
|
||||
m_timer.start(m_snackbar->autoHideDuration());
|
||||
if (m_snackbar->clickToDismissMode()) {
|
||||
m_snackbar->setAttribute(Qt::WA_TransparentForMouseEvents, false);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef QTMATERIALSNACKBAR_INTERNAL_H
|
||||
#define QTMATERIALSNACKBAR_INTERNAL_H
|
||||
|
||||
#include <QStateMachine>
|
||||
#include <QTimer>
|
||||
|
||||
class QtMaterialSnackbar;
|
||||
|
||||
class QtMaterialSnackbarStateMachine : public QStateMachine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(qreal offset WRITE setOffset READ offset)
|
||||
|
||||
public:
|
||||
QtMaterialSnackbarStateMachine(QtMaterialSnackbar *parent);
|
||||
~QtMaterialSnackbarStateMachine();
|
||||
|
||||
void setOffset(qreal offset);
|
||||
inline qreal offset() const;
|
||||
|
||||
public slots:
|
||||
void progress();
|
||||
|
||||
protected slots:
|
||||
void snackbarShown();
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QtMaterialSnackbarStateMachine)
|
||||
|
||||
QtMaterialSnackbar *const m_snackbar;
|
||||
QTimer m_timer;
|
||||
qreal m_offset;
|
||||
};
|
||||
|
||||
inline qreal QtMaterialSnackbarStateMachine::offset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
#endif // QTMATERIALSNACKBAR_INTERNAL_H
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef QTMATERIALSNACKBAR_P_H
|
||||
#define QTMATERIALSNACKBAR_P_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QColor>
|
||||
|
||||
class QtMaterialSnackbar;
|
||||
class QtMaterialSnackbarStateMachine;
|
||||
|
||||
class QtMaterialSnackbarPrivate
|
||||
{
|
||||
Q_DISABLE_COPY(QtMaterialSnackbarPrivate)
|
||||
Q_DECLARE_PUBLIC(QtMaterialSnackbar)
|
||||
|
||||
public:
|
||||
QtMaterialSnackbarPrivate(QtMaterialSnackbar *q);
|
||||
~QtMaterialSnackbarPrivate();
|
||||
|
||||
void init();
|
||||
|
||||
QtMaterialSnackbar *const q_ptr;
|
||||
QtMaterialSnackbarStateMachine *stateMachine;
|
||||
QColor backgroundColor;
|
||||
QColor textColor;
|
||||
qreal bgOpacity;
|
||||
QList<QString> messages;
|
||||
int duration;
|
||||
int boxWidth;
|
||||
bool clickDismiss;
|
||||
bool useThemeColors;
|
||||
};
|
||||
|
||||
#endif // QTMATERIALSNACKBAR_P_H
|
Loading…
Reference in New Issue