Add Snackbar files

This commit is contained in:
johanneshilden 2017-09-29 16:58:00 +03:00
parent 231f01b5a6
commit 5a7d6ee7a1
5 changed files with 500 additions and 0 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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