Add overlayMode property to QtMaterialDrawer

This commit is contained in:
johanneshilden 2017-10-07 15:54:56 +03:00
parent fc1fb1ef8e
commit 3a7d7a19fd
6 changed files with 239 additions and 68 deletions

View File

@ -2,6 +2,7 @@
#include "qtmaterialdrawer_p.h"
#include <QPainter>
#include <QEvent>
#include <QDebug>
#include <QMouseEvent>
#include <QtWidgets/QApplication>
#include <QtWidgets/QLayout>
@ -36,17 +37,25 @@ void QtMaterialDrawerPrivate::init()
{
Q_Q(QtMaterialDrawer);
stateMachine = new QtMaterialDrawerStateMachine(q);
widget = new QtMaterialDrawerWidget;
stateMachine = new QtMaterialDrawerStateMachine(widget, q);
window = new QWidget;
width = 250;
clickToClose = false;
autoRaise = true;
closed = true;
overlay = false;
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(window);
q->setLayout(layout);
q->setFixedWidth(width+16);
widget->setLayout(layout);
widget->setFixedWidth(width+16);
widget->setParent(q);
q->setAttribute(Qt::WA_TransparentForMouseEvents);
q->setAttribute(Qt::WA_NoSystemBackground);
stateMachine->start();
QCoreApplication::processEvents();
@ -73,7 +82,7 @@ void QtMaterialDrawer::setDrawerWidth(int width)
d->width = width;
d->stateMachine->updatePropertyAssignments();
setFixedWidth(width+16);
d->widget->setFixedWidth(width+16);
}
int QtMaterialDrawer::drawerWidth() const
@ -125,22 +134,43 @@ bool QtMaterialDrawer::autoRaise() const
return d->autoRaise;
}
void QtMaterialDrawer::setOverlayMode(bool value)
{
Q_D(QtMaterialDrawer);
d->overlay = value;
}
bool QtMaterialDrawer::overlayMode() const
{
Q_D(const QtMaterialDrawer);
return d->overlay;
}
void QtMaterialDrawer::openDrawer()
{
Q_D(QtMaterialDrawer);
emit d->stateMachine->enterOpenedState();
emit d->stateMachine->signalOpen();
if (d->autoRaise) {
raise();
}
if (d->overlay) {
setAttribute(Qt::WA_TransparentForMouseEvents, false);
setAttribute(Qt::WA_NoSystemBackground, false);
}
}
void QtMaterialDrawer::closeDrawer()
{
Q_D(QtMaterialDrawer);
emit d->stateMachine->enterClosedState();
emit d->stateMachine->signalClose();
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_NoSystemBackground);
}
bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
@ -152,7 +182,8 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
case QEvent::MouseButtonPress: {
QMouseEvent *mouseEvent;
if ((mouseEvent = static_cast<QMouseEvent *>(event))) {
if (!geometry().contains(mouseEvent->pos()) && d->clickToClose) {
const bool canClose = d->clickToClose || d->overlay;
if (!d->widget->geometry().contains(mouseEvent->pos()) && canClose) {
closeDrawer();
}
}
@ -160,9 +191,9 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
}
case QEvent::Move:
case QEvent::Resize: {
QLayout *lyut = layout();
if (lyut && 16 != lyut->contentsMargins().right()) {
lyut->setContentsMargins(0, 0, 16, 0);
QLayout *lout = d->widget->layout();
if (lout && 16 != lout->contentsMargins().right()) {
lout->setContentsMargins(0, 0, 16, 0);
}
}
default:
@ -175,28 +206,13 @@ void QtMaterialDrawer::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
Q_D(QtMaterialDrawer);
if (!d->overlay || d->stateMachine->isInClosedState()) {
return;
}
QPainter painter(this);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::white);
painter.setBrush(brush);
painter.setPen(Qt::NoPen);
painter.drawRect(rect().adjusted(0, 0, -16, 0));
QLinearGradient gradient(QPointF(width()-16, 0), QPointF(width(), 0));
gradient.setColorAt(0, QColor(0, 0, 0, 80));
gradient.setColorAt(0.5, QColor(0, 0, 0, 20));
gradient.setColorAt(1, QColor(0, 0, 0, 0));
painter.setBrush(QBrush(gradient));
painter.drawRect(width()-16, 0, 16, height());
}
QRect QtMaterialDrawer::overlayGeometry() const
{
Q_D(const QtMaterialDrawer);
return QtMaterialOverlayWidget::overlayGeometry().translated(d->stateMachine->offset(), 0);
painter.setOpacity(d->stateMachine->opacity());
painter.fillRect(rect(), Qt::SolidPattern);
}

View File

@ -26,6 +26,9 @@ public:
void setAutoRaise(bool state);
bool autoRaise() const;
void setOverlayMode(bool value);
bool overlayMode() const;
public slots:
void openDrawer();
void closeDrawer();
@ -34,8 +37,6 @@ protected:
bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
QRect overlayGeometry() const Q_DECL_OVERRIDE;
const QScopedPointer<QtMaterialDrawerPrivate> d_ptr;
private:

View File

@ -1,17 +1,29 @@
#include "qtmaterialdrawer_internal.h"
#include <QState>
#include <QPainter>
#include <QtWidgets/QLayout>
#include <QSignalTransition>
#include <QPropertyAnimation>
#include "qtmaterialdrawer.h"
QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer)
: QStateMachine(drawer),
/*!
* \class QtMaterialDrawerStateMachine
* \internal
*/
QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawerWidget *drawer, QtMaterialDrawer *parent)
: QStateMachine(parent),
m_drawer(drawer),
m_openState(new QState),
m_main(parent),
m_openingState(new QState),
m_openedState(new QState),
m_closingState(new QState),
m_closedState(new QState),
m_offset(0)
m_opacity(0)
{
addState(m_openState);
addState(m_openingState);
addState(m_openedState);
addState(m_closingState);
addState(m_closedState);
setInitialState(m_closedState);
@ -19,24 +31,57 @@ QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *dra
QSignalTransition *transition;
QPropertyAnimation *animation;
transition = new QSignalTransition(this, SIGNAL(enterOpenedState()));
transition->setTargetState(m_openState);
transition = new QSignalTransition(this, SIGNAL(signalOpen()));
transition->setTargetState(m_openingState);
m_closedState->addTransition(transition);
animation = new QPropertyAnimation(this, "offset", this);
animation = new QPropertyAnimation(drawer, "offset", this);
animation->setDuration(220);
animation->setEasingCurve(QEasingCurve::OutCirc);
transition->addAnimation(animation);
transition = new QSignalTransition(this, SIGNAL(enterClosedState()));
transition->setTargetState(m_closedState);
m_openState->addTransition(transition);
animation = new QPropertyAnimation(this, "opacity", this);
animation->setDuration(220);
transition->addAnimation(animation);
animation = new QPropertyAnimation(this, "offset", this);
transition = new QSignalTransition(animation, SIGNAL(finished()));
transition->setTargetState(m_openedState);
m_openingState->addTransition(transition);
transition = new QSignalTransition(this, SIGNAL(signalClose()));
transition->setTargetState(m_closingState);
m_openingState->addTransition(transition);
animation = new QPropertyAnimation(this, "opacity", this);
animation->setDuration(220);
transition->addAnimation(animation);
animation = new QPropertyAnimation(drawer, "offset", this);
animation->setDuration(220);
animation->setEasingCurve(QEasingCurve::InCirc);
transition->addAnimation(animation);
transition = new QSignalTransition(animation, SIGNAL(finished()));
transition->setTargetState(m_closedState);
m_closingState->addTransition(transition);
transition = new QSignalTransition(this, SIGNAL(signalClose()));
transition->setTargetState(m_closingState);
m_openedState->addTransition(transition);
animation = new QPropertyAnimation(drawer, "offset", this);
animation->setDuration(220);
animation->setEasingCurve(QEasingCurve::InCirc);
transition->addAnimation(animation);
animation = new QPropertyAnimation(this, "opacity", this);
animation->setDuration(220);
transition->addAnimation(animation);
transition = new QSignalTransition(animation, SIGNAL(finished()));
transition->setTargetState(m_closedState);
m_closingState->addTransition(transition);
updatePropertyAssignments();
}
@ -44,18 +89,81 @@ QtMaterialDrawerStateMachine::~QtMaterialDrawerStateMachine()
{
}
void QtMaterialDrawerStateMachine::setOffset(int offset)
void QtMaterialDrawerStateMachine::setOpacity(qreal opacity)
{
m_offset = offset;
m_opacity = opacity;
m_main->update();
}
QWidget *widget = m_drawer->parentWidget();
if (widget) {
m_drawer->setGeometry(widget->rect().translated(offset, 0));
}
bool QtMaterialDrawerStateMachine::isInClosedState() const
{
return m_closedState->active();
}
void QtMaterialDrawerStateMachine::updatePropertyAssignments()
{
m_closedState->assignProperty(this, "offset", -(m_drawer->width()+32));
m_openState->assignProperty(this, "offset", 0);
const qreal closedOffset = -(m_drawer->width()+32);
m_closingState->assignProperty(m_drawer, "offset", closedOffset);
m_closedState->assignProperty(m_drawer, "offset", closedOffset);
m_closingState->assignProperty(this, "opacity", 0);
m_closedState->assignProperty(this, "opacity", 0);
m_openingState->assignProperty(m_drawer, "offset", 0);
m_openingState->assignProperty(this, "opacity", 0.4);
}
/*!
* \class QtMaterialDrawerWidget
* \internal
*/
QtMaterialDrawerWidget::QtMaterialDrawerWidget(QWidget *parent)
: QtMaterialOverlayWidget(parent),
m_offset(0)
{
}
QtMaterialDrawerWidget::~QtMaterialDrawerWidget()
{
}
void QtMaterialDrawerWidget::setOffset(int offset)
{
m_offset = offset;
QWidget *widget = parentWidget();
if (widget) {
setGeometry(widget->rect().translated(offset, 0));
}
update();
}
void QtMaterialDrawerWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(Qt::white);
painter.setBrush(brush);
painter.setPen(Qt::NoPen);
painter.drawRect(rect().adjusted(0, 0, -16, 0));
QLinearGradient gradient(QPointF(width()-16, 0), QPointF(width(), 0));
gradient.setColorAt(0, QColor(0, 0, 0, 80));
gradient.setColorAt(0.5, QColor(0, 0, 0, 20));
gradient.setColorAt(1, QColor(0, 0, 0, 0));
painter.setBrush(QBrush(gradient));
painter.drawRect(width()-16, 0, 16, height());
}
QRect QtMaterialDrawerWidget::overlayGeometry() const
{
return QtMaterialOverlayWidget::overlayGeometry().translated(m_offset, 0);
}

View File

@ -2,35 +2,75 @@
#define DRAWER_INTERNAL_H
#include <QStateMachine>
#include "lib/qtmaterialoverlaywidget.h"
class QtMaterialDrawer;
class QtMaterialDrawerWidget;
class QtMaterialDrawerStateMachine : public QStateMachine
{
Q_OBJECT
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
public:
explicit QtMaterialDrawerStateMachine(QtMaterialDrawerWidget *drawer,
QtMaterialDrawer *parent);
~QtMaterialDrawerStateMachine();
void setOpacity(qreal opacity);
inline qreal opacity() const;
bool isInClosedState() const;
void updatePropertyAssignments();
signals:
void signalOpen();
void signalClose();
private:
Q_DISABLE_COPY(QtMaterialDrawerStateMachine)
QtMaterialDrawerWidget *const m_drawer;
QtMaterialDrawer *const m_main;
QState *const m_openingState;
QState *const m_openedState;
QState *const m_closingState;
QState *const m_closedState;
qreal m_opacity;
};
inline qreal QtMaterialDrawerStateMachine::opacity() const
{
return m_opacity;
}
class QtMaterialDrawerWidget : public QtMaterialOverlayWidget
{
Q_OBJECT
Q_PROPERTY(int offset WRITE setOffset READ offset)
public:
explicit QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer);
~QtMaterialDrawerStateMachine();
explicit QtMaterialDrawerWidget(QWidget *parent = 0);
~QtMaterialDrawerWidget();
void setOffset(int offset);
inline int offset() const { return m_offset; }
inline int offset() const;
void updatePropertyAssignments();
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
signals:
void enterOpenedState();
void enterClosedState();
QRect overlayGeometry() const Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QtMaterialDrawerStateMachine)
QtMaterialDrawer *const m_drawer;
QState *const m_openState;
QState *const m_closedState;
int m_offset;
int m_offset;
};
inline int QtMaterialDrawerWidget::offset() const
{
return m_offset;
}
#endif // DRAWER_INTERNAL_H

View File

@ -4,6 +4,7 @@
#include <QObject>
class QtMaterialDrawer;
class QtMaterialDrawerWidget;
class QtMaterialDrawerStateMachine;
class QtMaterialDrawerPrivate
@ -16,13 +17,17 @@ public:
~QtMaterialDrawerPrivate();
void init();
void setClosed(bool value = true);
QtMaterialDrawer *const q_ptr;
QtMaterialDrawerWidget *widget;
QtMaterialDrawerStateMachine *stateMachine;
QWidget *window;
int width;
bool clickToClose;
bool autoRaise;
bool closed;
bool overlay;
};
#endif // DRAWER_P_H

View File

@ -27,6 +27,7 @@ DrawerSettingsEditor::DrawerSettingsEditor(QWidget *parent)
m_drawer->setParent(this);
m_drawer->setClickOutsideToClose(true);
m_drawer->setOverlayMode(true);
setupForm();