diff --git a/README.md b/README.md index f108a56..584f546 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ - [x] Check Box - [x] Circular Progress - [x] Dialog -- [ ] Drawer +- [x] Drawer - [x] Floating Action Button - [x] Flat Button - [x] Icon Button diff --git a/components/components.pro b/components/components.pro index 83ffe78..021bd62 100644 --- a/components/components.pro +++ b/components/components.pro @@ -35,7 +35,9 @@ SOURCES = \ qtmaterialscrollbar_internal.cpp \ qtmaterialscrollbar.cpp \ qtmaterialdialog_internal.cpp \ - qtmaterialdialog.cpp + qtmaterialdialog.cpp \ + qtmaterialdrawer_internal.cpp \ + qtmaterialdrawer.cpp HEADERS = \ qtmaterialavatar_p.h \ qtmaterialavatar.h \ @@ -92,6 +94,9 @@ HEADERS = \ qtmaterialscrollbar.h \ qtmaterialdialog_internal.h \ qtmaterialdialog_p.h \ - qtmaterialdialog.h + qtmaterialdialog.h \ + qtmaterialdrawer_internal.h \ + qtmaterialdrawer_p.h \ + qtmaterialdrawer.h RESOURCES += \ resources.qrc diff --git a/components/qtmaterialdrawer.cpp b/components/qtmaterialdrawer.cpp new file mode 100644 index 0000000..923d31c --- /dev/null +++ b/components/qtmaterialdrawer.cpp @@ -0,0 +1,123 @@ +#include "qtmaterialdrawer.h" +#include "qtmaterialdrawer_p.h" +#include +#include +#include +#include +#include +#include +#include "qtmaterialdrawer_internal.h" + +QtMaterialDrawerPrivate::QtMaterialDrawerPrivate(QtMaterialDrawer *q) + : q_ptr(q), + stateMachine(new QtMaterialDrawerStateMachine(q)), + window(new QWidget), + width(250) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(window); + + q->setLayout(layout); + q->setFixedWidth(width+16); + + stateMachine->start(); + + QCoreApplication::processEvents(); +} + +QtMaterialDrawer::QtMaterialDrawer(QWidget *parent) + : QtMaterialOverlayWidget(parent), + d_ptr(new QtMaterialDrawerPrivate(this)) +{ +} + +QtMaterialDrawer::~QtMaterialDrawer() +{ +} + +void QtMaterialDrawer::setDrawerWidth(int width) +{ + Q_D(QtMaterialDrawer); + + d->width = width; + d->stateMachine->updatePropertyAssignments(); + setFixedWidth(width+16); +} + +int QtMaterialDrawer::drawerWidth() const +{ + Q_D(const QtMaterialDrawer); + + return d->width; +} + +void QtMaterialDrawer::setDrawerLayout(QLayout *layout) +{ + Q_D(QtMaterialDrawer); + + d->window->setLayout(layout); +} + +QLayout *QtMaterialDrawer::drawerLayout() const +{ + Q_D(const QtMaterialDrawer); + + return d->window->layout(); +} + +void QtMaterialDrawer::openDrawer() +{ + Q_D(QtMaterialDrawer); + + emit d->stateMachine->enterOpenedState(); +} + +void QtMaterialDrawer::closeDrawer() +{ + Q_D(QtMaterialDrawer); + + emit d->stateMachine->enterClosedState(); +} + +bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event) +{ + const QEvent::Type type = event->type(); + + if (QEvent::Move == type || QEvent::Resize == type) { + QLayout *t = layout(); + if (t && 16 != t->contentsMargins().right()) { + t->setContentsMargins(0, 0, 16, 0); + } + } + return QtMaterialOverlayWidget::eventFilter(obj, event); +} + +void QtMaterialDrawer::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 QtMaterialDrawer::overlayGeometry() const +{ + Q_D(const QtMaterialDrawer); + + return QtMaterialOverlayWidget::overlayGeometry().translated(d->stateMachine->offset(), 0); +} diff --git a/components/qtmaterialdrawer.h b/components/qtmaterialdrawer.h new file mode 100644 index 0000000..35c7371 --- /dev/null +++ b/components/qtmaterialdrawer.h @@ -0,0 +1,40 @@ +#ifndef QTMATERIALDRAWER_H +#define QTMATERIALDRAWER_H + +#include "lib/qtmaterialoverlaywidget.h" + +class QtMaterialDrawerPrivate; +class QtMaterialDrawerStateMachine; + +class QtMaterialDrawer : public QtMaterialOverlayWidget +{ + Q_OBJECT + +public: + explicit QtMaterialDrawer(QWidget *parent = 0); + ~QtMaterialDrawer(); + + void setDrawerWidth(int width); + int drawerWidth() const; + + void setDrawerLayout(QLayout *layout); + QLayout *drawerLayout() const; + +protected slots: + void openDrawer(); + void closeDrawer(); + +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 d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialDrawer) + Q_DECLARE_PRIVATE(QtMaterialDrawer) +}; + +#endif // QTMATERIALDRAWER_H diff --git a/components/qtmaterialdrawer_internal.cpp b/components/qtmaterialdrawer_internal.cpp new file mode 100644 index 0000000..6751def --- /dev/null +++ b/components/qtmaterialdrawer_internal.cpp @@ -0,0 +1,61 @@ +#include "qtmaterialdrawer_internal.h" +#include +#include +#include +#include "qtmaterialdrawer.h" + +QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer) + : QStateMachine(drawer), + m_drawer(drawer), + m_openState(new QState), + m_closedState(new QState), + m_offset(0) +{ + addState(m_openState); + addState(m_closedState); + + setInitialState(m_closedState); + + QSignalTransition *transition; + QPropertyAnimation *animation; + + transition = new QSignalTransition(this, SIGNAL(enterOpenedState())); + transition->setTargetState(m_openState); + m_closedState->addTransition(transition); + + animation = new QPropertyAnimation(this, "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, "offset", this); + animation->setDuration(220); + animation->setEasingCurve(QEasingCurve::InCirc); + transition->addAnimation(animation); + + updatePropertyAssignments(); +} + +QtMaterialDrawerStateMachine::~QtMaterialDrawerStateMachine() +{ +} + +void QtMaterialDrawerStateMachine::setOffset(int offset) +{ + m_offset = offset; + + QWidget *widget = m_drawer->parentWidget(); + if (widget) { + m_drawer->setGeometry(widget->rect().translated(offset, 0)); + } +} + +void QtMaterialDrawerStateMachine::updatePropertyAssignments() +{ + m_closedState->assignProperty(this, "offset", -(m_drawer->width()+32)); + m_openState->assignProperty(this, "offset", 0); +} diff --git a/components/qtmaterialdrawer_internal.h b/components/qtmaterialdrawer_internal.h new file mode 100644 index 0000000..746620d --- /dev/null +++ b/components/qtmaterialdrawer_internal.h @@ -0,0 +1,36 @@ +#ifndef DRAWER_INTERNAL_H +#define DRAWER_INTERNAL_H + +#include + +class QtMaterialDrawer; + +class QtMaterialDrawerStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(int offset WRITE setOffset READ offset) + +public: + explicit QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer); + ~QtMaterialDrawerStateMachine(); + + void setOffset(int offset); + inline int offset() const { return m_offset; } + + void updatePropertyAssignments(); + +signals: + void enterOpenedState(); + void enterClosedState(); + +private: + Q_DISABLE_COPY(QtMaterialDrawerStateMachine) + + QtMaterialDrawer *const m_drawer; + QState *const m_openState; + QState *const m_closedState; + int m_offset; +}; + +#endif // DRAWER_INTERNAL_H diff --git a/components/qtmaterialdrawer_p.h b/components/qtmaterialdrawer_p.h new file mode 100644 index 0000000..dcb6e19 --- /dev/null +++ b/components/qtmaterialdrawer_p.h @@ -0,0 +1,23 @@ +#ifndef DRAWER_P_H +#define DRAWER_P_H + +#include + +class QtMaterialDrawer; +class QtMaterialDrawerStateMachine; + +class QtMaterialDrawerPrivate +{ + Q_DISABLE_COPY(QtMaterialDrawerPrivate) + Q_DECLARE_PUBLIC(QtMaterialDrawer) + +public: + QtMaterialDrawerPrivate(QtMaterialDrawer *q); + + QtMaterialDrawer *const q_ptr; + QtMaterialDrawerStateMachine *const stateMachine; + QWidget *const window; + int width; +}; + +#endif // DRAWER_P_H diff --git a/components/qtmaterialsnackbar.cpp b/components/qtmaterialsnackbar.cpp index 2614af1..7cce48e 100644 --- a/components/qtmaterialsnackbar.cpp +++ b/components/qtmaterialsnackbar.cpp @@ -97,7 +97,9 @@ void QtMaterialSnackbar::setBackgroundColor(const QColor &color) Q_D(QtMaterialSnackbar); d->backgroundColor = color; - setUseThemeColors(false); + + MATERIAL_DISABLE_THEME_COLORS + update(); } QColor QtMaterialSnackbar::backgroundColor() const @@ -131,7 +133,9 @@ void QtMaterialSnackbar::setTextColor(const QColor &color) Q_D(QtMaterialSnackbar); d->textColor = color; - setUseThemeColors(false); + + MATERIAL_DISABLE_THEME_COLORS + update(); } QColor QtMaterialSnackbar::textColor() const diff --git a/examples/dialogsettingseditor.cpp b/examples/dialogsettingseditor.cpp index 729d17b..611aba2 100644 --- a/examples/dialogsettingseditor.cpp +++ b/examples/dialogsettingseditor.cpp @@ -24,8 +24,6 @@ DialogSettingsEditor::DialogSettingsEditor(QWidget *parent) layout = new QVBoxLayout; canvas->setLayout(layout); canvas->setMaximumHeight(300); - layout->addWidget(m_dialog); - layout->setAlignment(m_dialog, Qt::AlignHCenter); m_dialog->setParent(this); diff --git a/examples/drawersettingseditor.cpp b/examples/drawersettingseditor.cpp new file mode 100644 index 0000000..48d988f --- /dev/null +++ b/examples/drawersettingseditor.cpp @@ -0,0 +1,47 @@ +#include "drawersettingseditor.h" +#include +#include +#include "qtmaterialdrawer.h" + +DrawerSettingsEditor::DrawerSettingsEditor(QWidget *parent) + : QWidget(parent), + ui(new Ui::DrawerSettingsForm), + m_drawer(new QtMaterialDrawer) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + + QWidget *widget = new QWidget; + layout->addWidget(widget); + + QWidget *canvas = new QWidget; + canvas->setStyleSheet("QWidget { background: white; }"); + layout->addWidget(canvas); + + ui->setupUi(widget); + layout->setContentsMargins(20, 20, 20, 20); + + layout = new QVBoxLayout; + canvas->setLayout(layout); + canvas->setMaximumHeight(300); + + m_drawer->setParent(this); + + setupForm(); + + connect(ui->showDrawerButton, SIGNAL(pressed()), m_drawer, SLOT(openDrawer())); + connect(ui->hideDrawerButton, SIGNAL(pressed()), m_drawer, SLOT(closeDrawer())); +} + +DrawerSettingsEditor::~DrawerSettingsEditor() +{ + delete ui; +} + +void DrawerSettingsEditor::setupForm() +{ +} + +void DrawerSettingsEditor::updateWidget() +{ +} diff --git a/examples/drawersettingseditor.h b/examples/drawersettingseditor.h new file mode 100644 index 0000000..45f21af --- /dev/null +++ b/examples/drawersettingseditor.h @@ -0,0 +1,26 @@ +#ifndef DRAWERSETTINGSEDITOR_H +#define DRAWERSETTINGSEDITOR_H + +#include +#include "ui_drawersettingsform.h" + +class QtMaterialDrawer; + +class DrawerSettingsEditor : public QWidget +{ + Q_OBJECT + +public: + explicit DrawerSettingsEditor(QWidget *parent = 0); + ~DrawerSettingsEditor(); + +protected slots: + void setupForm(); + void updateWidget(); + +private: + Ui::DrawerSettingsForm *const ui; + QtMaterialDrawer *const m_drawer; +}; + +#endif // DRAWERSETTINGSEDITOR_H diff --git a/examples/drawersettingsform.ui b/examples/drawersettingsform.ui new file mode 100644 index 0000000..b5c7a2a --- /dev/null +++ b/examples/drawersettingsform.ui @@ -0,0 +1,58 @@ + + + DrawerSettingsForm + + + + 0 + 0 + 474 + 387 + + + + Form + + + + + 10 + 70 + 171 + 16 + + + + TODO + + + + + + 340 + 20 + 101 + 22 + + + + Show drawer + + + + + + 340 + 50 + 101 + 22 + + + + Hide drawer + + + + + + diff --git a/examples/examples.pro b/examples/examples.pro index 3527648..4e97bf4 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -17,7 +17,8 @@ SOURCES = mainwindow.cpp \ textfieldsettingseditor.cpp \ tabssettingseditor.cpp \ snackbarsettingseditor.cpp \ - dialogsettingseditor.cpp + dialogsettingseditor.cpp \ + drawersettingseditor.cpp HEADERS = mainwindow.h \ avatarsettingseditor.h \ badgesettingseditor.h \ @@ -34,7 +35,8 @@ HEADERS = mainwindow.h \ textfieldsettingseditor.h \ tabssettingseditor.h \ snackbarsettingseditor.h \ - dialogsettingseditor.h + dialogsettingseditor.h \ + drawersettingseditor.h LIBS += ../components/libcomponents.a INCLUDEPATH += ../components/ TARGET = ../examples-exe @@ -57,4 +59,5 @@ FORMS += \ togglesettingsform.ui \ textfieldsettingsform.ui \ tabssettingsform.ui \ - dialogsettingsform.ui + dialogsettingsform.ui \ + drawersettingsform.ui diff --git a/examples/mainwindow.cpp b/examples/mainwindow.cpp index 4a0b24f..a41aa36 100644 --- a/examples/mainwindow.cpp +++ b/examples/mainwindow.cpp @@ -18,6 +18,7 @@ #include "tabssettingseditor.h" #include "snackbarsettingseditor.h" #include "dialogsettingseditor.h" +#include "drawersettingseditor.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -53,12 +54,14 @@ MainWindow::MainWindow(QWidget *parent) TabsSettingsEditor *tabs = new TabsSettingsEditor; SnackbarSettingsEditor *snackbar = new SnackbarSettingsEditor; DialogSettingsEditor *dialog = new DialogSettingsEditor; + DrawerSettingsEditor *drawer = new DrawerSettingsEditor; stack->addWidget(avatar); stack->addWidget(badge); stack->addWidget(checkbox); stack->addWidget(circularProgress); stack->addWidget(dialog); + stack->addWidget(drawer); stack->addWidget(fab); stack->addWidget(flatButton); stack->addWidget(iconButton); @@ -76,6 +79,7 @@ MainWindow::MainWindow(QWidget *parent) list->addItem("Checkbox"); list->addItem("Circular Progress"); list->addItem("Dialog"); + list->addItem("Drawer"); list->addItem("Floating Action Button"); list->addItem("Flat Button"); list->addItem("Icon Button");