From c47e969300870b147c4abbf79b6c76f2b86d0070 Mon Sep 17 00:00:00 2001 From: laserpants Date: Sun, 19 Jun 2016 15:49:42 +0300 Subject: [PATCH] implement ScrollBar --- components/circularprogress_internal.h | 12 +- components/scrollbar.cpp | 152 +++++++++++++++++++++++++ components/scrollbar.h | 36 ++++++ components/scrollbar_internal.cpp | 51 +++++++++ components/scrollbar_internal.h | 30 +++++ components/scrollbar_p.h | 28 +++++ examples/avatarexamples.cpp | 4 + qt-material-widgets.pro | 11 +- 8 files changed, 314 insertions(+), 10 deletions(-) create mode 100644 components/scrollbar_internal.cpp create mode 100644 components/scrollbar_internal.h create mode 100644 components/scrollbar_p.h diff --git a/components/circularprogress_internal.h b/components/circularprogress_internal.h index 05b7935..420553e 100644 --- a/components/circularprogress_internal.h +++ b/components/circularprogress_internal.h @@ -16,14 +16,14 @@ public: CircularProgressDelegate(CircularProgress *parent); ~CircularProgressDelegate(); - void setDashOffset(qreal offset) { _dashOffset = offset; progress->update(); } - qreal dashOffset() const { return _dashOffset; } + inline void setDashOffset(qreal offset) { _dashOffset = offset; progress->update(); } + inline qreal dashOffset() const { return _dashOffset; } - void setDashLength(qreal value) { _dashLength = value; progress->update(); } - qreal dashLength() const { return _dashLength; } + inline void setDashLength(qreal value) { _dashLength = value; progress->update(); } + inline qreal dashLength() const { return _dashLength; } - void setAngle(int angle) { _angle = angle; progress->update(); } - int angle() const { return _angle; } + inline void setAngle(int angle) { _angle = angle; progress->update(); } + inline int angle() const { return _angle; } private: Q_DISABLE_COPY(CircularProgressDelegate) diff --git a/components/scrollbar.cpp b/components/scrollbar.cpp index d7a5791..23996b3 100644 --- a/components/scrollbar.cpp +++ b/components/scrollbar.cpp @@ -1 +1,153 @@ #include "scrollbar.h" +#include +#include +#include "scrollbar_p.h" +#include "scrollbar_internal.h" +#include "lib/style.h" + +ScrollBarPrivate::ScrollBarPrivate(ScrollBar *q) + : q_ptr(q), + machine(0), + hideOnMouseOut(true), + useThemeColors(true) +{ +} + +ScrollBarPrivate::~ScrollBarPrivate() +{ +} + +void ScrollBarPrivate::init() +{ + Q_Q(ScrollBar); + + q->setMouseTracking(true); + + machine = new ScrollBarStateMachine(q); + machine->start(); + + QCoreApplication::processEvents(); +} + +ScrollBar::ScrollBar(QWidget *parent) + : QScrollBar(parent), + d_ptr(new ScrollBarPrivate(this)) +{ + d_func()->init(); +} + +ScrollBar::~ScrollBar() +{ +} + +void ScrollBar::setUseThemeColors(bool value) +{ + Q_D(ScrollBar); + + d->useThemeColors = value; + update(); +} + +bool ScrollBar::useThemeColors() const +{ + Q_D(const ScrollBar); + + return d->useThemeColors; +} + +void ScrollBar::setBackgroundColor(const QColor &color) +{ + Q_D(ScrollBar); + + d->backgroundColor = color; + setUseThemeColors(false); +} + +QColor ScrollBar::backgroundColor() const +{ + Q_D(const ScrollBar); + + if (d->useThemeColors || !d->backgroundColor.isValid()) { + return Style::instance().themeColor("border").darker(110); + } else { + return d->backgroundColor; + } +} + +void ScrollBar::setSliderColor(const QColor &color) +{ + Q_D(ScrollBar); + + d->sliderColor = color; + setUseThemeColors(false); +} + +QColor ScrollBar::sliderColor() const +{ + Q_D(const ScrollBar); + + if (d->useThemeColors || !d->sliderColor.isValid()) { + return Style::instance().themeColor("primary1"); + } else { + return d->sliderColor; + } +} + +void ScrollBar::setHideOnMouseOut(bool state) +{ + Q_D(ScrollBar); + + d->hideOnMouseOut = state; + update(); +} + +bool ScrollBar::hideOnMouseOut() const +{ + Q_D(const ScrollBar); + + return d->hideOnMouseOut; +} + +QSize ScrollBar::sizeHint() const +{ + return QSize(10, 1); +} + +void ScrollBar::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + Q_D(ScrollBar); + + QPainter painter(this); + + painter.fillRect(rect(), palette().color(QPalette::Window)); + + int x, y, w, h; + rect().getRect(&x, &y, &w, &h); + + QMargins margins(2, 2, 2, 2); + + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(backgroundColor()); + painter.setBrush(brush); + painter.setPen(Qt::NoPen); + + if (d->hideOnMouseOut) { + painter.setOpacity(d->machine->opacity()); + } + + painter.drawRect(rect().marginsRemoved(margins)); + + const qreal q = h / static_cast(maximum() - minimum() + pageStep()); + + QRect handle = Qt::Horizontal == orientation() + ? QRect(sliderPosition()*q, y, pageStep()*q, h) + : QRect(x, sliderPosition()*q, w, pageStep()*q); + + brush.setColor(sliderColor()); + painter.setBrush(brush); + + painter.drawRect(handle.marginsRemoved(margins)); +} diff --git a/components/scrollbar.h b/components/scrollbar.h index 22e976b..ab88548 100644 --- a/components/scrollbar.h +++ b/components/scrollbar.h @@ -1,4 +1,40 @@ #ifndef SCROLLBAR_H #define SCROLLBAR_H +#include + +class ScrollBarPrivate; + +class ScrollBar : public QScrollBar +{ + Q_OBJECT + +public: + explicit ScrollBar(QWidget *parent = 0); + ~ScrollBar(); + + void setUseThemeColors(bool value); + bool useThemeColors() const; + + void setBackgroundColor(const QColor &color); + QColor backgroundColor() const; + + void setSliderColor(const QColor &color); + QColor sliderColor() const; + + void setHideOnMouseOut(bool state); + bool hideOnMouseOut() const; + + QSize sizeHint() const Q_DECL_OVERRIDE; + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(ScrollBar) + Q_DECLARE_PRIVATE(ScrollBar) +}; + #endif // SCROLLBAR_H diff --git a/components/scrollbar_internal.cpp b/components/scrollbar_internal.cpp new file mode 100644 index 0000000..31b392e --- /dev/null +++ b/components/scrollbar_internal.cpp @@ -0,0 +1,51 @@ +#include "scrollbar_internal.h" +#include +#include + +ScrollBarStateMachine::ScrollBarStateMachine(ScrollBar *parent) + : QStateMachine(parent), + scrollBar(parent), + _opacity(0) +{ + QState *focusState = new QState; + QState *blurState = new QState; + + addState(focusState); + addState(blurState); + + setInitialState(blurState); + + QEventTransition *transition; + + // + + transition = new QEventTransition(parent, QEvent::HoverEnter); + transition->setTargetState(focusState); + + blurState->addTransition(transition); + + // + + transition = new QEventTransition(parent, QEvent::HoverLeave); + transition->setTargetState(blurState); + + focusState->addTransition(transition); + + // + + focusState->assignProperty(this, "opacity", 1); + blurState->assignProperty(this, "opacity", 0); + + // + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(this, "opacity"); + animation->setDuration(340); + + addDefaultAnimation(animation); +} + +ScrollBarStateMachine::~ScrollBarStateMachine() +{ +} diff --git a/components/scrollbar_internal.h b/components/scrollbar_internal.h new file mode 100644 index 0000000..594aec5 --- /dev/null +++ b/components/scrollbar_internal.h @@ -0,0 +1,30 @@ +#ifndef SCROLLBAR_INTERNAL_H +#define SCROLLBAR_INTERNAL_H + +#include +#include "scrollbar.h" + +class ScrollBar; + +class ScrollBarStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + +public: + ScrollBarStateMachine(ScrollBar *parent); + ~ScrollBarStateMachine(); + + inline void setOpacity(qreal opacity) { _opacity = opacity; scrollBar->update(); } + inline qreal opacity() const { return _opacity; } + +private: + Q_DISABLE_COPY(ScrollBarStateMachine) + + ScrollBar *const scrollBar; + qreal _opacity; +}; + +#endif // SCROLLBAR_INTERNAL_H + diff --git a/components/scrollbar_p.h b/components/scrollbar_p.h new file mode 100644 index 0000000..42f1bdb --- /dev/null +++ b/components/scrollbar_p.h @@ -0,0 +1,28 @@ +#ifndef SCROLLBAR_P_H +#define SCROLLBAR_P_H + +#include + +class ScrollBar; +class ScrollBarStateMachine; + +class ScrollBarPrivate +{ + Q_DISABLE_COPY(ScrollBarPrivate) + Q_DECLARE_PUBLIC(ScrollBar) + +public: + ScrollBarPrivate(ScrollBar *q); + ~ScrollBarPrivate(); + + void init(); + + ScrollBar *const q_ptr; + ScrollBarStateMachine *machine; + QColor backgroundColor; + QColor sliderColor; + bool hideOnMouseOut; + bool useThemeColors; +}; + +#endif // SCROLLBAR_P_H diff --git a/examples/avatarexamples.cpp b/examples/avatarexamples.cpp index 2767365..f21e479 100644 --- a/examples/avatarexamples.cpp +++ b/examples/avatarexamples.cpp @@ -6,12 +6,16 @@ #include "components/badge.h" #include "exampleview.h" #include "frame.h" +#include "components/scrollbar.h" AvatarExamples::AvatarExamples(QWidget *parent) : ExampleList(parent) { QLayout *layout = widget()->layout(); + ScrollBar *sb = new ScrollBar; + setVerticalScrollBar(sb); + { Avatar *avatar = new Avatar; diff --git a/qt-material-widgets.pro b/qt-material-widgets.pro index d0ba175..3cc5af8 100644 --- a/qt-material-widgets.pro +++ b/qt-material-widgets.pro @@ -46,7 +46,6 @@ SOURCES += main.cpp\ examples/avatarexamples.cpp \ examples/menuexamples.cpp \ components/menu.cpp \ - components/scrollbar.cpp \ examples/iconmenuexamples.cpp \ lib/scaleeffect.cpp \ lib/style.cpp \ @@ -68,7 +67,9 @@ SOURCES += main.cpp\ components/snackbar_internal.cpp \ components/circularprogress.cpp \ components/circularprogress_internal.cpp \ - components/progress_internal.cpp + components/progress_internal.cpp \ + components/scrollbar.cpp \ + components/scrollbar_internal.cpp HEADERS += mainwindow.h \ components/appbar.h \ @@ -109,7 +110,6 @@ HEADERS += mainwindow.h \ examples/avatarexamples.h \ examples/menuexamples.h \ components/menu.h \ - components/scrollbar.h \ examples/iconmenuexamples.h \ lib/scaleeffect.h \ lib/style.h \ @@ -147,7 +147,10 @@ HEADERS += mainwindow.h \ components/circularprogress.h \ components/circularprogress_p.h \ components/circularprogress_internal.h \ - components/progress_internal.h + components/progress_internal.h \ + components/scrollbar.h \ + components/scrollbar_p.h \ + components/scrollbar_internal.h RESOURCES += \ resources.qrc