diff --git a/mainwindow.cpp b/mainwindow.cpp index bbce67b..2bb600a 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -56,6 +56,7 @@ #include "yy/togglesettingseditor.h" #include "components/snackbar.h" #include "xx/qtmaterialsnackbar.h" +#include "xx/qtmaterialdialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -210,11 +211,31 @@ MainWindow::MainWindow(QWidget *parent) layout->addStretch(); */ + { + QtMaterialDialog *mdlg = new QtMaterialDialog; + mdlg->setParent(this); + + QVBoxLayout *dl = new QVBoxLayout; + dl->addWidget(new QPushButton("Hello")); + mdlg->setWindowLayout(dl); + + QPushButton *b1 = new QPushButton("1"); + QPushButton *b2 = new QPushButton("2"); + b1->setParent(this); + b2->setParent(this); + b1->setGeometry(10, 160, 30, 20); + b2->setGeometry(10, 190, 30, 20); + + connect(b1, SIGNAL(pressed()), mdlg, SLOT(showDialog())); + connect(b2, SIGNAL(pressed()), mdlg, SLOT(hideDialog())); + } + + Drawer *drwer = new Drawer; drwer->setParent(this); Dialog *dlg = new Dialog; - //dlg->setParent(this); + dlg->setParent(this); //dlg->windowLayout()->addWidget(new QPushButton("Hello")); QVBoxLayout *dl = new QVBoxLayout; @@ -224,8 +245,8 @@ MainWindow::MainWindow(QWidget *parent) QPushButton *bbbtn = new QPushButton("Show dialog"); layout->addWidget(bbbtn); - //connect(bbbtn, SIGNAL(pressed()), dlg, SLOT(showDialog())); - connect(bbbtn, SIGNAL(pressed()), drwer, SLOT(openDrawer())); + connect(bbbtn, SIGNAL(pressed()), dlg, SLOT(showDialog())); + //connect(bbbtn, SIGNAL(pressed()), drwer, SLOT(openDrawer())); QtMaterialIconMenu *im = new QtMaterialIconMenu(QIcon("../qt-material-widgets/ic_star_black_24px.svg")); layout->addWidget(im); @@ -268,6 +289,7 @@ MainWindow::MainWindow(QWidget *parent) } QtMaterialSelectField *sfp = new QtMaterialSelectField; + sfp->setPlaceholderText("Favorite language"); //sfp->setBackgroundColor(Qt::white); layout->addWidget(sfp); layout->setAlignment(sfp, Qt::AlignCenter); diff --git a/qt-material-widgets.pro b/qt-material-widgets.pro index 15588d7..4907ddb 100644 --- a/qt-material-widgets.pro +++ b/qt-material-widgets.pro @@ -136,7 +136,9 @@ SOURCES += main.cpp\ yy/togglesettingseditor.cpp \ xx/qtmaterialsnackbar.cpp \ xx/qtmaterialsnackbar_internal.cpp \ - xxlib/qtmaterialstatetransition.cpp + xxlib/qtmaterialstatetransition.cpp \ + xx/qtmaterialdialog.cpp \ + xx/qtmaterialdialog_internal.cpp HEADERS += mainwindow.h \ components/appbar.h \ @@ -311,7 +313,10 @@ HEADERS += mainwindow.h \ xx/qtmaterialsnackbar_p.h \ xx/qtmaterialsnackbar_internal.h \ xxlib/qtmaterialstatetransitionevent.h \ - xxlib/qtmaterialstatetransition.h + xxlib/qtmaterialstatetransition.h \ + xx/qtmaterialdialog.h \ + xx/qtmaterialdialog_internal.h \ + xx/qtmaterialdialog_p.h RESOURCES += \ resources.qrc diff --git a/xx/qtmaterialcollapsiblemenu.cpp b/xx/qtmaterialcollapsiblemenu.cpp index eeef39e..269e8c4 100644 --- a/xx/qtmaterialcollapsiblemenu.cpp +++ b/xx/qtmaterialcollapsiblemenu.cpp @@ -48,6 +48,12 @@ void QtMaterialCollapsibleMenuPrivate::init() scrollArea->setWidgetResizable(true); scrollArea->setWidget(mainWidget); scrollArea->setVerticalScrollBar(scrollBar); + + scrollArea->setAutoFillBackground(true); + QPalette p(scrollArea->palette()); + p.setColor(QPalette::Background, Qt::white); + scrollArea->setPalette(p); + scrollBar->setHideOnMouseOut(false); proxyStack->addWidget(scrollArea); diff --git a/xx/qtmaterialcollapsiblemenu_internal.cpp b/xx/qtmaterialcollapsiblemenu_internal.cpp index 49dc5ff..f144daf 100644 --- a/xx/qtmaterialcollapsiblemenu_internal.cpp +++ b/xx/qtmaterialcollapsiblemenu_internal.cpp @@ -30,6 +30,7 @@ QtMaterialCollapsibleMenuStateMachine::QtMaterialCollapsibleMenuStateMachine( setInitialState(m_collapsedState); QtMaterialStateTransition *transition; + QPropertyAnimation *animation; transition = new QtMaterialStateTransition(CollapsibleMenuExpand); transition->setTargetState(m_expandedState); @@ -43,10 +44,17 @@ QtMaterialCollapsibleMenuStateMachine::QtMaterialCollapsibleMenuStateMachine( m_expandYAnimation->setTargetObject(m_proxy); m_expandYAnimation->setPropertyName("yScale"); - m_expandYAnimation->setDuration(500); + m_expandYAnimation->setDuration(600); m_expandYAnimation->setEasingCurve(QEasingCurve::OutElastic); transition->addAnimation(m_expandYAnimation); + animation = new QPropertyAnimation(this); + animation->setTargetObject(m_proxy); + animation->setPropertyName("opacity"); + animation->setDuration(220); + animation->setEasingCurve(QEasingCurve::OutQuad); + transition->addAnimation(animation); + transition = new QtMaterialStateTransition(CollapsibleMenuCollapse); transition->setTargetState(m_collapsedState); m_expandedState->addTransition(transition); @@ -71,11 +79,11 @@ QtMaterialCollapsibleMenuStateMachine::QtMaterialCollapsibleMenuStateMachine( m_collapsedState->assignProperty(m_proxy, "yScale", 0.05); m_collapsedState->assignProperty(m_proxy, "opacity", 0); - QPropertyAnimation *animation = new QPropertyAnimation(this); + animation = new QPropertyAnimation(this); animation->setTargetObject(m_proxy); animation->setPropertyName("opacity"); - animation->setDuration(160); - addDefaultAnimation(animation); + animation->setDuration(140); + transition->addAnimation(animation); connect(m_expandedState, SIGNAL(propertiesAssigned()), m_menu, SLOT(setOpaque())); diff --git a/xx/qtmaterialcollapsiblemenu_internal.h b/xx/qtmaterialcollapsiblemenu_internal.h index 0ee6876..582684e 100644 --- a/xx/qtmaterialcollapsiblemenu_internal.h +++ b/xx/qtmaterialcollapsiblemenu_internal.h @@ -94,10 +94,6 @@ public: inline void setOpacity(qreal opacity); inline qreal opacity() const; -//signals: -// void expand(); -// void collapse(); - protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; diff --git a/xx/qtmaterialdialog.cpp b/xx/qtmaterialdialog.cpp new file mode 100644 index 0000000..f572402 --- /dev/null +++ b/xx/qtmaterialdialog.cpp @@ -0,0 +1,166 @@ +#include "xx/qtmaterialdialog.h" +#include "xx/qtmaterialdialog_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "xx/qtmaterialdialog_internal.h" +#include "xxlib/qtmaterialstatetransition.h" + +/*! + * \class QtMaterialDialogPrivate + * \internal + */ + +QtMaterialDialogPrivate::QtMaterialDialogPrivate(QtMaterialDialog *q) + : q_ptr(q) +{ +} + +QtMaterialDialogPrivate::~QtMaterialDialogPrivate() +{ +} + +void QtMaterialDialogPrivate::init() +{ + Q_Q(QtMaterialDialog); + + dialogWindow = new QtMaterialDialogWindow(q); + proxyStack = new QStackedLayout; + stateMachine = new QStateMachine(q); + proxy = new QtMaterialDialogProxy(dialogWindow, proxyStack, q); + + QVBoxLayout *layout = new QVBoxLayout; + q->setLayout(layout); + + QWidget *widget = new QWidget; + widget->setLayout(proxyStack); + widget->setMinimumWidth(400); + + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + effect->setColor(QColor(0, 0, 0, 200)); + effect->setBlurRadius(64); + effect->setOffset(0, 13); + widget->setGraphicsEffect(effect); + + layout->addWidget(widget); + layout->setAlignment(widget, Qt::AlignCenter); + + proxyStack->addWidget(dialogWindow); + proxyStack->addWidget(proxy); + proxyStack->setCurrentIndex(1); + + q->setAttribute(Qt::WA_TransparentForMouseEvents); + + QState *hiddenState = new QState; + QState *visibleState = new QState; + + stateMachine->addState(hiddenState); + stateMachine->addState(visibleState); + stateMachine->setInitialState(hiddenState); + + QtMaterialStateTransition *transition; + + transition = new QtMaterialStateTransition(DialogShowTransition); + transition->setTargetState(visibleState); + hiddenState->addTransition(transition); + + transition = new QtMaterialStateTransition(DialogHideTransition); + transition->setTargetState(hiddenState); + visibleState->addTransition(transition); + + visibleState->assignProperty(proxy, "opacity", 1); + visibleState->assignProperty(effect, "color", QColor(0, 0, 0, 200)); + visibleState->assignProperty(dialogWindow, "offset", 0); + hiddenState->assignProperty(proxy, "opacity", 0); + hiddenState->assignProperty(effect, "color", QColor(0, 0, 0, 0)); + hiddenState->assignProperty(dialogWindow, "offset", 200); + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(proxy, "opacity", q); + animation->setDuration(280); + stateMachine->addDefaultAnimation(animation); + + animation = new QPropertyAnimation(effect, "color", q); + animation->setDuration(280); + stateMachine->addDefaultAnimation(animation); + + animation = new QPropertyAnimation(dialogWindow, "offset", q); + animation->setDuration(280); + animation->setEasingCurve(QEasingCurve::OutCirc); + stateMachine->addDefaultAnimation(animation); + + QObject::connect(visibleState, SIGNAL(propertiesAssigned()), + proxy, SLOT(makeOpaque())); + QObject::connect(hiddenState, SIGNAL(propertiesAssigned()), + proxy, SLOT(makeTransparent())); + + stateMachine->start(); + QCoreApplication::processEvents(); +} + +/*! + * \class QtMaterialDialog + */ + +QtMaterialDialog::QtMaterialDialog(QWidget *parent) + : QtMaterialOverlayWidget(parent), + d_ptr(new QtMaterialDialogPrivate(this)) +{ + d_func()->init(); +} + +QtMaterialDialog::~QtMaterialDialog() +{ +} + +QLayout *QtMaterialDialog::windowLayout() const +{ + Q_D(const QtMaterialDialog); + + return d->dialogWindow->layout(); +} + +void QtMaterialDialog::setWindowLayout(QLayout *layout) +{ + Q_D(QtMaterialDialog); + + d->dialogWindow->setLayout(layout); +} + +void QtMaterialDialog::showDialog() +{ + Q_D(QtMaterialDialog); + + d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(DialogShowTransition)); +} + +void QtMaterialDialog::hideDialog() +{ + Q_D(QtMaterialDialog); + + d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(DialogHideTransition)); + setAttribute(Qt::WA_TransparentForMouseEvents); + d->proxyStack->setCurrentIndex(1); +} + +void QtMaterialDialog::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + Q_D(QtMaterialDialog); + + QPainter painter(this); + + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::black); + painter.setBrush(brush); + painter.setPen(Qt::NoPen); + painter.setOpacity(d->proxy->opacity()/2.4); + painter.drawRect(rect()); +} diff --git a/xx/qtmaterialdialog.h b/xx/qtmaterialdialog.h new file mode 100644 index 0000000..3cf8f2a --- /dev/null +++ b/xx/qtmaterialdialog.h @@ -0,0 +1,35 @@ +#ifndef QTMATERIALDIALOG_H +#define QTMATERIALDIALOG_H + +#include +#include "xxlib/qtmaterialoverlaywidget.h" + +class QLayout; +class QtMaterialDialogPrivate; + +class QtMaterialDialog : public QtMaterialOverlayWidget +{ + Q_OBJECT + +public: + explicit QtMaterialDialog(QWidget *parent = 0); + ~QtMaterialDialog(); + + QLayout *windowLayout() const; + void setWindowLayout(QLayout *layout); + +protected slots: + void showDialog(); + void hideDialog(); + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialDialog) + Q_DECLARE_PRIVATE(QtMaterialDialog) +}; + +#endif // QTMATERIALDIALOG_H diff --git a/xx/qtmaterialdialog_internal.cpp b/xx/qtmaterialdialog_internal.cpp new file mode 100644 index 0000000..ba1e40d --- /dev/null +++ b/xx/qtmaterialdialog_internal.cpp @@ -0,0 +1,127 @@ +#include "xx/qtmaterialdialog_internal.h" +#include +#include +#include +#include +#include "xx/qtmaterialdialog.h" + +/*! + * \class QtMaterialDialogProxy + * \internal + */ + +QtMaterialDialogProxy::QtMaterialDialogProxy( + QtMaterialDialogWindow *source, + QStackedLayout *layout, + QtMaterialDialog *dialog, + QWidget *parent) + : QWidget(parent), + m_source(source), + m_layout(layout), + m_dialog(dialog), + m_opacity(0), + m_mode(Transparent) +{ +} + +QtMaterialDialogProxy::~QtMaterialDialogProxy() +{ +} + +void QtMaterialDialogProxy::setOpacity(qreal opacity) +{ + m_opacity = opacity; + m_mode = SemiTransparent; + update(); + m_dialog->update(); +} + + +void QtMaterialDialogProxy::makeOpaque() +{ + m_dialog->setAttribute(Qt::WA_TransparentForMouseEvents, false); + m_layout->setCurrentIndex(0); + m_opacity = 1.0; + m_mode = Opaque; + update(); +} + +void QtMaterialDialogProxy::makeTransparent() +{ + m_opacity = 0.0; + m_mode = Transparent; + update(); +} + +QSize QtMaterialDialogProxy::sizeHint() const +{ + return m_source->sizeHint(); +} + +bool QtMaterialDialogProxy::event(QEvent *event) +{ + const QEvent::Type type = event->type(); + + if (QEvent::Move == type || QEvent::Resize == type) { + m_source->setGeometry(geometry()); + } + return QWidget::event(event); +} + +void QtMaterialDialogProxy::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + if (Transparent == m_mode) { + return; + } else if (Opaque != m_mode) { + painter.setOpacity(m_opacity); + } + QPixmap pm = m_source->grab(m_source->rect()); + painter.drawPixmap(0, 0, pm); +} + +/*! + * \class QtMaterialDialogWindow + * \internal + */ + +QtMaterialDialogWindow::QtMaterialDialogWindow( + QtMaterialDialog *dialog, + QWidget *parent) + : QWidget(parent), + m_dialog(dialog) +{ +} + +QtMaterialDialogWindow::~QtMaterialDialogWindow() +{ +} + +void QtMaterialDialogWindow::setOffset(int offset) +{ + QMargins margins = m_dialog->layout()->contentsMargins(); + margins.setBottom(offset); + m_dialog->layout()->setContentsMargins(margins); +} + +int QtMaterialDialogWindow::offset() const +{ + return m_dialog->layout()->contentsMargins().bottom(); +} + +void QtMaterialDialogWindow::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::white); + painter.setPen(Qt::NoPen); + painter.setBrush(brush); + painter.drawRect(rect()); +} diff --git a/xx/qtmaterialdialog_internal.h b/xx/qtmaterialdialog_internal.h new file mode 100644 index 0000000..903c026 --- /dev/null +++ b/xx/qtmaterialdialog_internal.h @@ -0,0 +1,79 @@ +#ifndef QTMATERIALDIALOG_INTERNAL_H +#define QTMATERIALDIALOG_INTERNAL_H + +#include + +class QStackedLayout; +class QtMaterialDialog; +class QtMaterialDialogWindow; + +class QtMaterialDialogProxy : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + + enum TransparencyMode { + Transparent, + SemiTransparent, + Opaque, + }; + +public: + QtMaterialDialogProxy(QtMaterialDialogWindow *source, + QStackedLayout *layout, + QtMaterialDialog *dialog, + QWidget *parent = 0); + ~QtMaterialDialogProxy(); + + void setOpacity(qreal opacity); + inline qreal opacity() const; + +protected slots: + void makeOpaque(); + void makeTransparent(); + + QSize sizeHint() const Q_DECL_OVERRIDE; + +protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialDialogProxy) + + QtMaterialDialogWindow *const m_source; + QStackedLayout *const m_layout; + QtMaterialDialog *const m_dialog; + qreal m_opacity; + TransparencyMode m_mode; +}; + +inline qreal QtMaterialDialogProxy::opacity() const +{ + return m_opacity; +} + +class QtMaterialDialogWindow : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(int offset WRITE setOffset READ offset) + +public: + explicit QtMaterialDialogWindow(QtMaterialDialog *dialog, QWidget *parent = 0); + ~QtMaterialDialogWindow(); + + void setOffset(int offset); + int offset() const; + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialDialogWindow) + + QtMaterialDialog *const m_dialog; +}; + +#endif // QTMATERIALDIALOG_INTERNAL_H diff --git a/xx/qtmaterialdialog_p.h b/xx/qtmaterialdialog_p.h new file mode 100644 index 0000000..b10088e --- /dev/null +++ b/xx/qtmaterialdialog_p.h @@ -0,0 +1,30 @@ +#ifndef QTMATERIALDIALOG_P_H +#define QTMATERIALDIALOG_P_H + +#include + +class QStateMachine; +class QtMaterialDialog; +class QStackedLayout; +class QtMaterialDialogWindow; +class QtMaterialDialogProxy; + +class QtMaterialDialogPrivate +{ + Q_DISABLE_COPY(QtMaterialDialogPrivate) + Q_DECLARE_PUBLIC(QtMaterialDialog) + +public: + QtMaterialDialogPrivate(QtMaterialDialog *q); + ~QtMaterialDialogPrivate(); + + void init(); + + QtMaterialDialog *const q_ptr; + QtMaterialDialogWindow *dialogWindow; + QStackedLayout *proxyStack; + QStateMachine *stateMachine; + QtMaterialDialogProxy *proxy; +}; + +#endif // QTMATERIALDIALOG_P_H diff --git a/xx/qtmaterialiconmenu.cpp b/xx/qtmaterialiconmenu.cpp index d998b88..0a41741 100644 --- a/xx/qtmaterialiconmenu.cpp +++ b/xx/qtmaterialiconmenu.cpp @@ -112,7 +112,7 @@ void QtMaterialIconMenu::collapseDelayed() Q_D(QtMaterialIconMenu); if (d->autoCollapse) { - QTimer::singleShot(200, d->menu, SLOT(collapse())); + QTimer::singleShot(110, d->menu, SLOT(collapse())); } } diff --git a/xx/qtmaterialscrollbar.cpp b/xx/qtmaterialscrollbar.cpp index 05a61a1..7b0dfc1 100644 --- a/xx/qtmaterialscrollbar.cpp +++ b/xx/qtmaterialscrollbar.cpp @@ -94,7 +94,7 @@ QColor QtMaterialScrollBar::canvasColor() const Q_D(const QtMaterialScrollBar); if (d->useThemeColors || !d->canvasColor.isValid()) { - return QtMaterialStyle::instance().themeColor("canvas"); + return parentWidget()->palette().color(backgroundRole()); } else { return d->canvasColor; } @@ -182,7 +182,7 @@ void QtMaterialScrollBar::paintEvent(QPaintEvent *event) painter.drawRect(rect().marginsRemoved(margins)); - const qreal q = h / static_cast(maximum() - minimum() + pageStep()); + const qreal q = h / static_cast(maximum()-minimum()+pageStep()-1); QRect handle = Qt::Horizontal == orientation() ? QRect(sliderPosition()*q, y, pageStep()*q, h) diff --git a/xx/qtmaterialselectfield.cpp b/xx/qtmaterialselectfield.cpp index 86ff81f..25299d1 100644 --- a/xx/qtmaterialselectfield.cpp +++ b/xx/qtmaterialselectfield.cpp @@ -265,7 +265,7 @@ void QtMaterialSelectField::collapseDelayed() { Q_D(QtMaterialSelectField); - QTimer::singleShot(200, d->menu, SLOT(collapse())); + QTimer::singleShot(100, d->menu, SLOT(collapse())); } /*! diff --git a/xxlib/qtmaterialstatetransitionevent.h b/xxlib/qtmaterialstatetransitionevent.h index f985cc3..1c64ec6 100644 --- a/xxlib/qtmaterialstatetransitionevent.h +++ b/xxlib/qtmaterialstatetransitionevent.h @@ -21,7 +21,10 @@ enum QtMaterialStateTransitionType { SliderChangedFromMinimum, SliderNoFocusMouseEnter, SliderNoFocusMouseLeave, - + // Dialog + DialogShowTransition, + DialogHideTransition, + // MaxTransitionType = 65535 };