From 09405ad0be6560bcd367d621444f6bc207c910f9 Mon Sep 17 00:00:00 2001 From: laserpants Date: Sun, 12 Jun 2016 18:17:27 +0300 Subject: [PATCH] add clipping to FAB ripple --- components/fab.cpp | 82 +++++++++++++++++++++++++++++++++++-------- components/fab.h | 9 +++++ components/fab_p.h | 2 ++ lib/rippleoverlay.cpp | 2 +- lib/rippleoverlay.h | 6 ++-- mainwindow.cpp | 5 +-- 6 files changed, 86 insertions(+), 20 deletions(-) diff --git a/components/fab.cpp b/components/fab.cpp index d2da878..ff8bcef 100644 --- a/components/fab.cpp +++ b/components/fab.cpp @@ -6,6 +6,8 @@ FloatingActionButtonPrivate::FloatingActionButtonPrivate(FloatingActionButton *q) : RaisedButtonPrivate(q), mini(false), + offsX(34), + offsY(36), corner(Qt::BottomRightCorner) { } @@ -23,6 +25,11 @@ void FloatingActionButtonPrivate::init() q->setGeometry(fabGeometry()); assignAnimationProperties(); + + QPainterPath path; + path.addEllipse(0, 0, 56, 56); + ripple->setClipPath(path); + ripple->setClipping(true); } QRect FloatingActionButtonPrivate::fabGeometry() const @@ -33,27 +40,26 @@ QRect FloatingActionButtonPrivate::fabGeometry() const 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, + return QRect(offsX, + offsY, s, s); case Qt::TopRightCorner: - return QRect(parent->width() - offset, - offset - s, + return QRect(parent->width() - (offsX + s), + offsY, s, s); case Qt::BottomLeftCorner: - return QRect(offset -s, - parent->height() - offset, + return QRect(offsX, + parent->height() - (offsY + s), s, s); case Qt::BottomRightCorner: default: - return QRect(parent->width() - offset, - parent->height() - offset, + return QRect(parent->width() - (offsX + s), + parent->height() - (offsY + s), s, s); } } @@ -111,11 +117,13 @@ void FloatingActionButton::setMini(bool state) d->mini = state; - if (state) { - setFixedSize(40, 40); - } else { - setFixedSize(56, 56); - } + const int s = state ? 40 : 56; + + setFixedSize(s, s); + QPainterPath path; + path.addEllipse(0, 0, s, s); + d->ripple->setClipPath(path); + d->assignAnimationProperties(); update(); } @@ -145,6 +153,52 @@ Qt::Corner FloatingActionButton::corner() const return d->corner; } +void FloatingActionButton::setOffset(int x, int y) +{ + Q_D(FloatingActionButton); + + d->offsX = x; + d->offsY = y; + update(); +} + +QSize FloatingActionButton::offset() const +{ + Q_D(const FloatingActionButton); + + return QSize(d->offsX, d->offsY); +} + +void FloatingActionButton::setXOffset(int x) +{ + Q_D(FloatingActionButton); + + d->offsX = x; + update(); +} + +int FloatingActionButton::xOffset() const +{ + Q_D(const FloatingActionButton); + + return d->offsX; +} + +void FloatingActionButton::setYOffset(int y) +{ + Q_D(FloatingActionButton); + + d->offsY = y; + update(); +} + +int FloatingActionButton::yOffset() const +{ + Q_D(const FloatingActionButton); + + return d->offsY; +} + bool FloatingActionButton::event(QEvent *event) { QEvent::Type type = event->type(); diff --git a/components/fab.h b/components/fab.h index af377fb..18136c6 100644 --- a/components/fab.h +++ b/components/fab.h @@ -21,6 +21,15 @@ public: void setCorner(Qt::Corner corner); Qt::Corner corner() const; + void setOffset(int x, int y); + QSize offset() const; + + void setXOffset(int x); + int xOffset() const; + + void setYOffset(int y); + int yOffset() const; + protected: bool event(QEvent *event) Q_DECL_OVERRIDE; bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; diff --git a/components/fab_p.h b/components/fab_p.h index 376ece0..a7f7f64 100644 --- a/components/fab_p.h +++ b/components/fab_p.h @@ -19,6 +19,8 @@ public: void assignAnimationProperties(); bool mini; + int offsX; + int offsY; Qt::Corner corner; }; diff --git a/lib/rippleoverlay.cpp b/lib/rippleoverlay.cpp index dbef8ee..78572a1 100644 --- a/lib/rippleoverlay.cpp +++ b/lib/rippleoverlay.cpp @@ -46,7 +46,7 @@ void RippleOverlay::paintEvent(QPaintEvent *event) painter.setPen(Qt::NoPen); if (useClip) { - painter.setClipRegion(clipRegion); + painter.setClipPath(clipPath); } QList::const_iterator i; diff --git a/lib/rippleoverlay.h b/lib/rippleoverlay.h index a30d020..011e701 100644 --- a/lib/rippleoverlay.h +++ b/lib/rippleoverlay.h @@ -21,7 +21,7 @@ public: inline void setClipping(bool enabled) { useClip = enabled; update(); } inline bool hasClipping() const { return useClip; } - inline void setClipRegion(const QRegion ®ion) { clipRegion = region; update(); } + inline void setClipPath(const QPainterPath &path) { clipPath = path; update(); } protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; @@ -31,8 +31,8 @@ protected slots: private: QList ripples; - QRegion clipRegion; - bool useClip; + QPainterPath clipPath; + bool useClip; }; #endif // RIPPLEOVERLAY_H diff --git a/mainwindow.cpp b/mainwindow.cpp index b2b4d3f..b649322 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -48,15 +48,16 @@ MainWindow::MainWindow(QWidget *parent) FloatingActionButton *button = new FloatingActionButton(QIcon("../qt-material-widgets/ic_local_dining_white_24px.svg")); button->setParent(this); - button->setCorner(Qt::TopLeftCorner); + button->setCorner(Qt::TopRightCorner); button->setMini(true); + button->setYOffset(56); // FloatingActionButton *button2 = new FloatingActionButton(QIcon("../qt-material-widgets/ic_message_white_24px.svg")); button2->setParent(this); - button2->setDisabled(true); + //button2->setDisabled(true); } MainWindow::~MainWindow()