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 "qtmaterialdrawer_p.h"
#include <QPainter> #include <QPainter>
#include <QEvent> #include <QEvent>
#include <QDebug>
#include <QMouseEvent> #include <QMouseEvent>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <QtWidgets/QLayout> #include <QtWidgets/QLayout>
@ -36,17 +37,25 @@ void QtMaterialDrawerPrivate::init()
{ {
Q_Q(QtMaterialDrawer); Q_Q(QtMaterialDrawer);
stateMachine = new QtMaterialDrawerStateMachine(q); widget = new QtMaterialDrawerWidget;
stateMachine = new QtMaterialDrawerStateMachine(widget, q);
window = new QWidget; window = new QWidget;
width = 250; width = 250;
clickToClose = false; clickToClose = false;
autoRaise = true; autoRaise = true;
closed = true;
overlay = false;
QVBoxLayout *layout = new QVBoxLayout; QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(window); layout->addWidget(window);
q->setLayout(layout); widget->setLayout(layout);
q->setFixedWidth(width+16); widget->setFixedWidth(width+16);
widget->setParent(q);
q->setAttribute(Qt::WA_TransparentForMouseEvents);
q->setAttribute(Qt::WA_NoSystemBackground);
stateMachine->start(); stateMachine->start();
QCoreApplication::processEvents(); QCoreApplication::processEvents();
@ -73,7 +82,7 @@ void QtMaterialDrawer::setDrawerWidth(int width)
d->width = width; d->width = width;
d->stateMachine->updatePropertyAssignments(); d->stateMachine->updatePropertyAssignments();
setFixedWidth(width+16); d->widget->setFixedWidth(width+16);
} }
int QtMaterialDrawer::drawerWidth() const int QtMaterialDrawer::drawerWidth() const
@ -125,22 +134,43 @@ bool QtMaterialDrawer::autoRaise() const
return d->autoRaise; 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() void QtMaterialDrawer::openDrawer()
{ {
Q_D(QtMaterialDrawer); Q_D(QtMaterialDrawer);
emit d->stateMachine->enterOpenedState(); emit d->stateMachine->signalOpen();
if (d->autoRaise) { if (d->autoRaise) {
raise(); raise();
} }
if (d->overlay) {
setAttribute(Qt::WA_TransparentForMouseEvents, false);
setAttribute(Qt::WA_NoSystemBackground, false);
}
} }
void QtMaterialDrawer::closeDrawer() void QtMaterialDrawer::closeDrawer()
{ {
Q_D(QtMaterialDrawer); 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) bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
@ -152,7 +182,8 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
case QEvent::MouseButtonPress: { case QEvent::MouseButtonPress: {
QMouseEvent *mouseEvent; QMouseEvent *mouseEvent;
if ((mouseEvent = static_cast<QMouseEvent *>(event))) { 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(); closeDrawer();
} }
} }
@ -160,9 +191,9 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event)
} }
case QEvent::Move: case QEvent::Move:
case QEvent::Resize: { case QEvent::Resize: {
QLayout *lyut = layout(); QLayout *lout = d->widget->layout();
if (lyut && 16 != lyut->contentsMargins().right()) { if (lout && 16 != lout->contentsMargins().right()) {
lyut->setContentsMargins(0, 0, 16, 0); lout->setContentsMargins(0, 0, 16, 0);
} }
} }
default: default:
@ -175,28 +206,13 @@ void QtMaterialDrawer::paintEvent(QPaintEvent *event)
{ {
Q_UNUSED(event) Q_UNUSED(event)
Q_D(QtMaterialDrawer);
if (!d->overlay || d->stateMachine->isInClosedState()) {
return;
}
QPainter painter(this); QPainter painter(this);
painter.setOpacity(d->stateMachine->opacity());
QBrush brush; painter.fillRect(rect(), Qt::SolidPattern);
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);
} }

View File

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

View File

@ -1,17 +1,29 @@
#include "qtmaterialdrawer_internal.h" #include "qtmaterialdrawer_internal.h"
#include <QState> #include <QState>
#include <QPainter>
#include <QtWidgets/QLayout>
#include <QSignalTransition> #include <QSignalTransition>
#include <QPropertyAnimation> #include <QPropertyAnimation>
#include "qtmaterialdrawer.h" #include "qtmaterialdrawer.h"
QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer) /*!
: QStateMachine(drawer), * \class QtMaterialDrawerStateMachine
* \internal
*/
QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawerWidget *drawer, QtMaterialDrawer *parent)
: QStateMachine(parent),
m_drawer(drawer), 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_closedState(new QState),
m_offset(0) m_opacity(0)
{ {
addState(m_openState); addState(m_openingState);
addState(m_openedState);
addState(m_closingState);
addState(m_closedState); addState(m_closedState);
setInitialState(m_closedState); setInitialState(m_closedState);
@ -19,24 +31,57 @@ QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *dra
QSignalTransition *transition; QSignalTransition *transition;
QPropertyAnimation *animation; QPropertyAnimation *animation;
transition = new QSignalTransition(this, SIGNAL(enterOpenedState())); transition = new QSignalTransition(this, SIGNAL(signalOpen()));
transition->setTargetState(m_openState); transition->setTargetState(m_openingState);
m_closedState->addTransition(transition); m_closedState->addTransition(transition);
animation = new QPropertyAnimation(this, "offset", this); animation = new QPropertyAnimation(drawer, "offset", this);
animation->setDuration(220); animation->setDuration(220);
animation->setEasingCurve(QEasingCurve::OutCirc); animation->setEasingCurve(QEasingCurve::OutCirc);
transition->addAnimation(animation); transition->addAnimation(animation);
transition = new QSignalTransition(this, SIGNAL(enterClosedState())); animation = new QPropertyAnimation(this, "opacity", this);
transition->setTargetState(m_closedState); animation->setDuration(220);
m_openState->addTransition(transition); 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->setDuration(220);
animation->setEasingCurve(QEasingCurve::InCirc); animation->setEasingCurve(QEasingCurve::InCirc);
transition->addAnimation(animation); 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(); 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(); bool QtMaterialDrawerStateMachine::isInClosedState() const
if (widget) { {
m_drawer->setGeometry(widget->rect().translated(offset, 0)); return m_closedState->active();
}
} }
void QtMaterialDrawerStateMachine::updatePropertyAssignments() void QtMaterialDrawerStateMachine::updatePropertyAssignments()
{ {
m_closedState->assignProperty(this, "offset", -(m_drawer->width()+32)); const qreal closedOffset = -(m_drawer->width()+32);
m_openState->assignProperty(this, "offset", 0);
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 #define DRAWER_INTERNAL_H
#include <QStateMachine> #include <QStateMachine>
#include "lib/qtmaterialoverlaywidget.h"
class QtMaterialDrawer; class QtMaterialDrawer;
class QtMaterialDrawerWidget;
class QtMaterialDrawerStateMachine : public QStateMachine class QtMaterialDrawerStateMachine : public QStateMachine
{ {
Q_OBJECT 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) Q_PROPERTY(int offset WRITE setOffset READ offset)
public: public:
explicit QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer); explicit QtMaterialDrawerWidget(QWidget *parent = 0);
~QtMaterialDrawerStateMachine(); ~QtMaterialDrawerWidget();
void setOffset(int offset); 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: QRect overlayGeometry() const Q_DECL_OVERRIDE;
void enterOpenedState();
void enterClosedState();
private: private:
Q_DISABLE_COPY(QtMaterialDrawerStateMachine) int m_offset;
QtMaterialDrawer *const m_drawer;
QState *const m_openState;
QState *const m_closedState;
int m_offset;
}; };
inline int QtMaterialDrawerWidget::offset() const
{
return m_offset;
}
#endif // DRAWER_INTERNAL_H #endif // DRAWER_INTERNAL_H

View File

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

View File

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