From 49f9937545261699cef4a3effb6cfa6344f377ad Mon Sep 17 00:00:00 2001 From: laserpants Date: Sun, 12 Jun 2016 16:37:46 +0300 Subject: [PATCH] implement basic FAB style and functionality --- components/fab.cpp | 142 ++++++++++++++++++++++++++++-- components/fab.h | 7 +- components/fab_p.h | 5 ++ components/flatbutton.cpp | 1 + components/raisedbutton.cpp | 12 ++- components/raisedbutton.h | 2 + components/raisedbutton_p.h | 5 ++ examples/flatbuttonexamples.cpp | 21 +++-- examples/raisedbuttonexamples.cpp | 2 + mainwindow.cpp | 14 +++ 10 files changed, 193 insertions(+), 18 deletions(-) diff --git a/components/fab.cpp b/components/fab.cpp index 082e74d..daa6592 100644 --- a/components/fab.cpp +++ b/components/fab.cpp @@ -1,11 +1,12 @@ #include "fab.h" #include -#include +#include #include "fab_p.h" FloatingActionButtonPrivate::FloatingActionButtonPrivate(FloatingActionButton *q) : RaisedButtonPrivate(q), - mini(false) + mini(false), + corner(Qt::BottomRightCorner) { } @@ -18,12 +19,73 @@ void FloatingActionButtonPrivate::init() Q_Q(FloatingActionButton); q->setRole(Material::Primary); + q->setFixedSize(56, 56); + q->setGeometry(fabGeometry()); + + assignAnimationProperties(); } -FloatingActionButton::FloatingActionButton(QWidget *parent) - : RaisedButton(parent) +QRect FloatingActionButtonPrivate::fabGeometry() const +{ + Q_Q(const FloatingActionButton); + + QWidget *parent = q->parentWidget(); + if (!parent) + return QRect(); + + const int offset = mini ? 74 : 90; + const int s = mini ? 40 : 56; + + switch (corner) + { + case Qt::TopLeftCorner: + return QRect(offset - s, + offset - s, + s, s); + case Qt::TopRightCorner: + return QRect(parent->width() - offset, + offset - s, + s, s); + case Qt::BottomLeftCorner: + return QRect(offset -s, + parent->height() - offset, + s, s); + case Qt::BottomRightCorner: + default: + return QRect(parent->width() - offset, + parent->height() - offset, + s, s); + } +} + +void FloatingActionButtonPrivate::assignAnimationProperties() +{ + if (mini) + { + effect->setColor(QColor(0, 0, 0, 80)); + + normalState->assignProperty(effect, "offset", QPointF(0, 3)); + normalState->assignProperty(effect, "blurRadius", 13); + pressedState->assignProperty(effect, "offset", QPointF(0, 7)); + pressedState->assignProperty(effect, "blurRadius", 20); + } + else + { + effect->setColor(QColor(0, 0, 0, 110)); + + normalState->assignProperty(effect, "offset", QPointF(0, 6)); + normalState->assignProperty(effect, "blurRadius", 16); + pressedState->assignProperty(effect, "offset", QPointF(0, 11)); + pressedState->assignProperty(effect, "blurRadius", 28); + } +} + +FloatingActionButton::FloatingActionButton(const QIcon &icon, QWidget *parent) + : RaisedButton(*new FloatingActionButtonPrivate(this), parent) { d_func()->init(); + + setIcon(icon); } FloatingActionButton::~FloatingActionButton() @@ -44,7 +106,18 @@ void FloatingActionButton::setMini(bool state) { Q_D(FloatingActionButton); + if (d->mini == state) + return; + d->mini = state; + + if (state) { + setFixedSize(40, 40); + } else { + setFixedSize(56, 56); + } + d->assignAnimationProperties(); + update(); } bool FloatingActionButton::isMini() const @@ -54,11 +127,63 @@ bool FloatingActionButton::isMini() const return d->mini; } +void FloatingActionButton::setCorner(Qt::Corner corner) +{ + Q_D(FloatingActionButton); + + if (d->corner == corner) + return; + + d->corner = corner; + update(); +} + +Qt::Corner FloatingActionButton::corner() const +{ + Q_D(const FloatingActionButton); + + return d->corner; +} + +bool FloatingActionButton::event(QEvent *event) +{ + QEvent::Type type = event->type(); + + if (QEvent::ParentChange == type && parentWidget()) + { + Q_D(FloatingActionButton); + + parent()->installEventFilter(this); + setGeometry(d->fabGeometry()); + } + else if (QEvent::ParentAboutToChange == type && parentWidget()) + { + parent()->removeEventFilter(this); + } + return RaisedButton::event(event); +} + +bool FloatingActionButton::eventFilter(QObject *obj, QEvent *event) +{ + QEvent::Type type = event->type(); + + if (QEvent::Move == type || QEvent::Resize == type) + { + Q_D(FloatingActionButton); + + setGeometry(d->fabGeometry()); + } + return RaisedButton::eventFilter(obj, event); +} + void FloatingActionButton::paintEvent(QPaintEvent *event) { Q_UNUSED(event) - int s = qMin(width(), height()); + Q_D(FloatingActionButton); + + int s = d->mini ? 40 : 56; + QRect square = QRect(0, 0, s, s); square.moveCenter(rect().center()); @@ -73,4 +198,11 @@ void FloatingActionButton::paintEvent(QPaintEvent *event) painter.setPen(Qt::NoPen); painter.drawEllipse(square); + + const int sz = d->mini ? 18 : 24; + + QRect iconRect(0, 0, sz, sz); + iconRect.moveCenter(square.center()); + + icon().paint(&painter, iconRect, Qt::AlignCenter, QIcon::Normal); } diff --git a/components/fab.h b/components/fab.h index 332c4eb..af377fb 100644 --- a/components/fab.h +++ b/components/fab.h @@ -10,7 +10,7 @@ class FloatingActionButton : public RaisedButton Q_OBJECT public: - explicit FloatingActionButton(QWidget *parent = 0); + explicit FloatingActionButton(const QIcon &icon, QWidget *parent = 0); ~FloatingActionButton(); QSize sizeHint() const Q_DECL_OVERRIDE; @@ -18,7 +18,12 @@ public: void setMini(bool state); bool isMini() const; + void setCorner(Qt::Corner corner); + Qt::Corner corner() const; + protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private: diff --git a/components/fab_p.h b/components/fab_p.h index 0dd350d..376ece0 100644 --- a/components/fab_p.h +++ b/components/fab_p.h @@ -14,7 +14,12 @@ public: void init(); + QRect fabGeometry() const; + + void assignAnimationProperties(); + bool mini; + Qt::Corner corner; }; #endif // FAB_P_H diff --git a/components/flatbutton.cpp b/components/flatbutton.cpp index a24d7a1..ac0fc43 100644 --- a/components/flatbutton.cpp +++ b/components/flatbutton.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "lib/rippleoverlay.h" #include "lib/ripple.h" #include "flatbutton_p.h" diff --git a/components/raisedbutton.cpp b/components/raisedbutton.cpp index 6a2d2be..717d311 100644 --- a/components/raisedbutton.cpp +++ b/components/raisedbutton.cpp @@ -26,14 +26,14 @@ void RaisedButtonPrivate::init() q->setTextColor(Qt::white); q->setPeakOpacity(0.25); - QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + effect = new QGraphicsDropShadowEffect; effect->setBlurRadius(7); effect->setOffset(QPointF(0, 0)); effect->setColor(QColor(0, 0, 0, 60)); q->setGraphicsEffect(effect); - QState *normalState = new QState; - QState *pressedState = new QState; + normalState = new QState; + pressedState = new QState; machine.addState(normalState); machine.addState(pressedState); @@ -109,6 +109,12 @@ RaisedButton::~RaisedButton() { } +RaisedButton::RaisedButton(RaisedButtonPrivate &d, QWidget *parent) + : FlatButton(d, parent) +{ + d_func()->init(); +} + bool RaisedButton::event(QEvent *event) { Q_D(RaisedButton); diff --git a/components/raisedbutton.h b/components/raisedbutton.h index 56da659..d62dcbe 100644 --- a/components/raisedbutton.h +++ b/components/raisedbutton.h @@ -14,6 +14,8 @@ public: ~RaisedButton(); protected: + RaisedButton(RaisedButtonPrivate &d, QWidget *parent = 0); + bool event(QEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; diff --git a/components/raisedbutton_p.h b/components/raisedbutton_p.h index 00789ee..fb321f1 100644 --- a/components/raisedbutton_p.h +++ b/components/raisedbutton_p.h @@ -3,6 +3,8 @@ #include "flatbutton_p.h" +class QGraphicsDropShadowEffect; + class RaisedButtonPrivate : public FlatButtonPrivate { Q_DISABLE_COPY(RaisedButtonPrivate) @@ -15,6 +17,9 @@ public: void init(); QStateMachine machine; + QState *normalState; + QState *pressedState; + QGraphicsDropShadowEffect *effect; }; #endif // RAISEDBUTTON_P_H diff --git a/examples/flatbuttonexamples.cpp b/examples/flatbuttonexamples.cpp index 1d95319..648e045 100644 --- a/examples/flatbuttonexamples.cpp +++ b/examples/flatbuttonexamples.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "flatbuttonexamples.h" #include "lib/style.h" #include "components/flatbutton.h" @@ -206,18 +207,20 @@ FlatButtonExamples::FlatButtonExamples(QWidget *parent) //flatButton->setMinimumSize(200, 50); //flatButton->setCheckable(true); - FloatingActionButton *button = new FloatingActionButton; + FloatingActionButton *button = new FloatingActionButton(QIcon("../qt-material-widgets/ic_local_dining_white_24px.svg")); - ExampleView *view = new ExampleView; - view->setWidget(button); + //qDebug() << QGuiApplication::allWindows(); - Frame *frame = new Frame; - frame->setCodeSnippet( - "" - ); - frame->setWidget(view); + //ExampleView *view = new ExampleView; + //view->setWidget(button); - layout->addWidget(frame); + //Frame *frame = new Frame; + //frame->setCodeSnippet( + // "" + //); + //frame->setWidget(view); + + //layout->addWidget(frame); } } diff --git a/examples/raisedbuttonexamples.cpp b/examples/raisedbuttonexamples.cpp index 3a1af00..196a900 100644 --- a/examples/raisedbuttonexamples.cpp +++ b/examples/raisedbuttonexamples.cpp @@ -15,6 +15,8 @@ RaisedButtonExamples::RaisedButtonExamples(QWidget *parent) raisedButton->setText("Press me!"); raisedButton->setMaximumWidth(408); + raisedButton->setDisabled(true); + //raisedButton->setDisabled(true); //raisedButton->setFixedSize(400, 50); diff --git a/mainwindow.cpp b/mainwindow.cpp index dcf32de..b2b4d3f 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -20,6 +20,7 @@ #include "examples/avatarexamples.h" #include "examples/menuexamples.h" #include "examples/iconmenuexamples.h" +#include "components/fab.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -43,6 +44,19 @@ MainWindow::MainWindow(QWidget *parent) { _initWidget(); _initMenu(); + + FloatingActionButton *button = new FloatingActionButton(QIcon("../qt-material-widgets/ic_local_dining_white_24px.svg")); + button->setParent(this); + + button->setCorner(Qt::TopLeftCorner); + button->setMini(true); + + // + + FloatingActionButton *button2 = new FloatingActionButton(QIcon("../qt-material-widgets/ic_message_white_24px.svg")); + button2->setParent(this); + + button2->setDisabled(true); } MainWindow::~MainWindow()