diff --git a/components/appmenu.cpp b/components/appmenu.cpp new file mode 100644 index 0000000..2883861 --- /dev/null +++ b/components/appmenu.cpp @@ -0,0 +1,371 @@ +#include "appmenu.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "components/flatbutton.h" +#include "lib/sizeproxywidget.h" +#include "components/menu.h" + +AppMenu::AppMenu(QWidget *parent) + : QMenu(parent), + _menu(new Menu), + _proxyWidget(new SizeProxyWidget(_menu)) +{ + init(); + + ////SizeProxy *proxy = new SizeProxy(new QPushButton("XX")); + //_proxy = new SizeProxy(_menu); + //setLayout(_proxy); + + //_proxy->setScale(0.5, 0.5); + + ////_menu->setVisible(false); + //_menu->installEventFilter(this); + + //setMinimumSize(1, 1); + + //setLayout(new QVBoxLayout); + //layout()->setSpacing(0); + //layout()->setContentsMargins(0, 0, 0, 0); +} + +AppMenu::AppMenu(const QString &title, QWidget *parent) + : QMenu(title, parent), + _menu(new Menu), + _proxyWidget(new SizeProxyWidget(_menu)) +{ + init(); + + ////SizeProxy *proxy = new SizeProxy(new QPushButton("XX")); + //_proxy = new SizeProxy(_menu); + //setLayout(_proxy); + + //_proxy->setScale(0.5, 0.5); + + ////_menu->setVisible(false); + //_menu->installEventFilter(this); + + //setMinimumSize(1, 1); + + //QVBoxLayout *l = new QVBoxLayout; + //l->addWidget(_menu); + //setLayout(l); + + //SizeProxy *proxy = new SizeProxy(this); + //setLayout(proxy); + + //setLayout(new QVBoxLayout); + //layout()->setSpacing(0); + //layout()->setContentsMargins(0, 0, 0, 0); +} + +AppMenu::~AppMenu() +{ +} + +void AppMenu::animateExpand() +{ + QParallelAnimationGroup *group; + group = new QParallelAnimationGroup; + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation; + animation->setTargetObject(_proxyWidget); + animation->setPropertyName("canvasXScale"); + animation->setStartValue(0.5); + animation->setEndValue(1); + animation->setDuration(1350); + animation->setEasingCurve(QEasingCurve::OutQuad); + group->addAnimation(animation); + + animation = new QPropertyAnimation; + animation->setTargetObject(_proxyWidget); + animation->setPropertyName("canvasYScale"); + animation->setStartValue(0); + animation->setEndValue(1); + animation->setDuration(1350); + animation->setEasingCurve(QEasingCurve::OutQuad); + group->addAnimation(animation); + + animation = new QPropertyAnimation; + animation->setTargetObject(_proxyWidget); + animation->setPropertyName("xScale"); + animation->setStartValue(0.55); + animation->setEndValue(1); + animation->setDuration(1700); + animation->setEasingCurve(QEasingCurve::OutBounce); + group->addAnimation(animation); + + animation = new QPropertyAnimation; + animation->setTargetObject(_proxyWidget); + animation->setPropertyName("yScale"); + animation->setStartValue(0); + animation->setEndValue(1); + animation->setDuration(1700); + animation->setEasingCurve(QEasingCurve::OutBounce); + group->addAnimation(animation); + + animation = new QPropertyAnimation; + animation->setTargetObject(_proxyWidget); + animation->setPropertyName("opacity"); + animation->setStartValue(0); + animation->setEndValue(1); + animation->setDuration(1600); + group->addAnimation(animation); + + group->start(QAbstractAnimation::DeleteWhenStopped); +} + +//bool AppMenu::event(QEvent *event) +//{ +// switch (event->type()) +// { +// case QEvent::Resize: +// case QEvent::Move: { +// /* +// QList::const_iterator i; +// for (i = actions().begin(); i != actions().end(); ++i) { +// QAction *action = *i; +// FlatButton *item = menuItems.value(action); +// //item->setGeometry(actionGeometry(action)); +// } +// */ +// break; +// } +// default: +// break; +// } +// return QMenu::event(event); +//} + +bool AppMenu::eventFilter(QObject *obj, QEvent *event) +{ + if (QEvent::Resize == event->type()) { + + //setGeometry(_proxyWidget->geometry().translated(x(), y())); + + setGeometry(x(), y(), 400, 800); + + //setGeometry(_proxyWidget->sourceGeometry().translated(x(), y())); + + //QRect rect(_proxyWidget->sourceGeometry()); + + //rect.translate(x(), y()); + + //rect.setWidth(static_cast(rect.width())*_proxyWidget->canvasXScale()); + //rect.setHeight(static_cast(rect.height())*_proxyWidget->canvasYScale()); + + //setGeometry(rect); + + } + return QMenu::eventFilter(obj, event); +} + +//void AppMenu::actionEvent(QActionEvent *event) +//{ +// switch (event->type()) +// { +// case QEvent::ActionAdded: +// { +// break; +// +// QAction *action = event->action(); +// +// _menu->addMenuItem(action->text()); +// +// /* +// QAction *action = event->action(); +// FlatButton *button = new FlatButton; +// button->setText(action->text()); +// +// QFont font(button->font()); +// font.setCapitalization(QFont::MixedCase); +// font.setPointSize(11); +// font.setStyleName("Regular"); +// button->setFont(font); +// button->setMinimumHeight(48); +// button->setShowHalo(false); +// button->setParent(this); +// button->setIcon(QIcon("../qt-material-widgets/face.svg")); +// menuItems.insert(action, button); +// layout()->addWidget(button); +// */ +// break; +// } +// case QEvent::ActionRemoved: { +// break; +// } +// case QEvent::ActionChanged: { +// break; +// } +// default: +// break; +// } +// QMenu::actionEvent(event); +//} +// +//void AppMenu::mouseMoveEvent(QMouseEvent *event) +//{ +// Q_UNUSED(event) +//} + +void AppMenu::actionEvent(QActionEvent *event) +{ + switch (event->type()) + { + case QEvent::ActionAdded: + { + QAction *action = event->action(); + _menu->addMenuItem(action->text()); + break; + } + case QEvent::ActionRemoved: + { + break; + } + case QEvent::ActionChanged: + { + break; + } + default: + break; + } + QMenu::actionEvent(event); +} + +void AppMenu::mousePressEvent(QMouseEvent *event) +{ + Q_UNUSED(event) + + QMenu::mousePressEvent(event); +} + +void AppMenu::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + //painter.drawRect(rect()); + + //QBrush brush; + //brush.setStyle(Qt::SolidPattern); + //brush.setColor(Qt::white); + //painter.setOpacity(1.0); + //painter.setBrush(brush); + //painter.setPen(Qt::NoPen); + //painter.drawRect(rect()); + + //painter.drawRect(_proxyWidget->sourceGeometry()); + //painter.drawRect(rect()); + + //rect.setWidth(static_cast(rect.width())*_proxyWidget->canvasXScale()); + //rect.setHeight(static_cast(rect.height())*_proxyWidget->canvasYScale()); + + +// QPen pen; +// pen.setColor(Qt::red); +// pen.setWidth(3); +// painter.setPen(pen); +// painter.setBrush(Qt::NoBrush); +// +// //QRect r(rect()); +// //r.setWidth(static_cast(r.width())*_proxyWidget->xScale()); +// +// painter.drawRect(rect().adjusted(0, 0, -1, -1)); + + //QMenu::paintEvent(event); + +// QMenu::paintEvent(event); + + //QMenu::paintEvent(event); +// QList items = actions(); + +// if (!items.isEmpty()) +// { +// qreal h = static_cast(height())/items.length(); +// +// int c = 0; +// QList::const_iterator i; +// for (i = items.begin(); i != items.end(); ++i) { +// +// //cqDebug() << actionGeometry(*i); +// +// painter.drawRect(0, h*c++, width(), h); +// } +// } +} + +void AppMenu::init() +{ + //_menu->addMenuItem("adsfdsfadf"); + //_menu->addMenuItem("bdsfdsfadf"); + //_menu->addMenuItem("cdsfdsfadf"); + + +// _proxyWidget->show(); + //_proxyWidget->setParent(this); + //_proxyWidget->setWindowFlags(Qt::Widget); + //_proxyWidget->setAutoFillBackground(false); + //_proxyWidget->setAttribute( Qt::WA_TranslucentBackground, true ); + //_proxyWidget->setAttribute(Qt::WA_NoSystemBackground); + //_proxyWidget->setAttribute( Qt::WA_OpaquePaintEvent, false); + + //QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + //effect->setColor(QColor(0, 0, 0)); + //effect->setOffset(0, 1); + //effect->setBlurRadius(16); + + //_proxyWidget->setGraphicsEffect(effect); + + //setAutoFillBackground(true); + + //setPalette(Qt::transparent); + //setAutoFillBackground(false); + //setAttribute(Qt::WA_NoSystemBackground); + + setStyleSheet("QMenu { background-color: transparent; }"); + + QVBoxLayout *l = new QVBoxLayout; + l->addWidget(_proxyWidget); + l->setSizeConstraint(QLayout::SetMaximumSize); + l->setContentsMargins(0, 0, 0, 0); + setLayout(l); + + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + effect->setColor(QColor(0, 0, 0)); + effect->setOffset(0, 1); + effect->setBlurRadius(16); + + _proxyWidget->setGraphicsEffect(effect); + + //_proxyWidget->setXScale(1.0); + //_proxyWidget->setXScale(0.5); + //_proxyWidget->setYScale(1.0); + + connect(this, SIGNAL(aboutToShow()), this, SLOT(animateExpand())); + + _proxyWidget->installEventFilter(this); + + //_menu->installEventFilter(this); + + //setAttribute(Qt::WA_NoSystemBackground); +// setAttribute(Qt::WA_NoSystemBackground); + //_proxyWidget->setWindowFlags(_proxyWidget->windowFlags() | Qt::FramelessWindowHint); + //setAutoFillBackground(false); + + //setWindowFlags(windowFlags()); + + + //setAutoFillBackground(false); + + // _proxyWidget->setAttribute(Qt::WA_OpaquePaintEvent); + + //setMinimumSize(10, 10); +} diff --git a/components/appmenu.h b/components/appmenu.h new file mode 100644 index 0000000..ff11043 --- /dev/null +++ b/components/appmenu.h @@ -0,0 +1,46 @@ +#ifndef APPMENU_H +#define APPMENU_H + +#include + +class Menu; +class SizeProxyWidget; + +class AppMenu : public QMenu +{ + Q_OBJECT + +public: + explicit AppMenu(QWidget *parent = 0); + explicit AppMenu(const QString &title, QWidget *parent = 0); + ~AppMenu(); + + //QSize sizeHint() const; + +protected slots: + void animateExpand(); + +protected: + //bool event(QEvent *event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; + + //void actionEvent(QActionEvent *event) Q_DECL_OVERRIDE; + //void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + + void actionEvent(QActionEvent *event) Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(AppMenu) + //Q_DECLARE_PRIVATE(AppMenu) + + //QHash menuItems; + + void init(); + + Menu *_menu; + SizeProxyWidget *_proxyWidget; +}; + +#endif // APPMENU_H diff --git a/components/badge.cpp b/components/badge.cpp index cb6e798..f52d296 100644 --- a/components/badge.cpp +++ b/components/badge.cpp @@ -193,8 +193,7 @@ void Badge::setText(const QString &text) d->icon = QIcon(); } - QFontMetrics fm = fontMetrics(); - d->size = fm.size(Qt::TextShowMnemonic, text); + d->size = fontMetrics().size(Qt::TextShowMnemonic, text); update(); } diff --git a/components/collapsiblemenu.cpp b/components/collapsiblemenu.cpp new file mode 100644 index 0000000..d3f683b --- /dev/null +++ b/components/collapsiblemenu.cpp @@ -0,0 +1 @@ +#include "collapsiblemenu.h" diff --git a/components/collapsiblemenu.h b/components/collapsiblemenu.h new file mode 100644 index 0000000..388675b --- /dev/null +++ b/components/collapsiblemenu.h @@ -0,0 +1,10 @@ +#ifndef COLLAPSIBLEMENU_H +#define COLLAPSIBLEMENU_H + +#include + +class CollapsibleMenu : public QWidget +{ +}; + +#endif // COLLAPSIBLEMENU_H diff --git a/components/flatbutton.cpp b/components/flatbutton.cpp index 3143248..ea8ff9a 100644 --- a/components/flatbutton.cpp +++ b/components/flatbutton.cpp @@ -15,6 +15,7 @@ FlatButtonPrivate::FlatButtonPrivate(FlatButton *q) delegate(0), //new FlatButtonDelegate(q)), role(Material::Default), rippleStyle(Material::PositionedRipple), + iconPlacement(Material::LeftIcon), cornerRadius(3), bgMode(Qt::TransparentMode), useThemeColors(true), @@ -72,6 +73,22 @@ FlatButton::~FlatButton() { } +QSize FlatButton::sizeHint() const +{ + ensurePolished(); + + QSize size = fontMetrics().size(Qt::TextSingleLine, text()); + + int h = qMax(size.height(), iconSize().height()); + int w = size.width(); + + if (!icon().isNull()) { + w += iconSize().width()+12; + } + + return QSize(20+w, 20+h); +} + void FlatButton::setHasFixedRippleRadius(bool value) { Q_D(FlatButton); @@ -108,6 +125,21 @@ Material::RippleStyle FlatButton::rippleStyle() const return d->rippleStyle; } +void FlatButton::setIconPlacement(Material::IconPlacement placement) +{ + Q_D(FlatButton); + + d->iconPlacement = placement; + update(); +} + +Material::IconPlacement FlatButton::iconPlacement() const +{ + Q_D(const FlatButton); + + return d->iconPlacement; +} + void FlatButton::setCornerRadius(qreal radius) { Q_D(FlatButton); @@ -332,6 +364,40 @@ void FlatButton::paintEvent(QPaintEvent *event) paintHalo(&painter); + // + + painter.setPen(textColor()); + painter.setOpacity(1); + + if (icon().isNull()) + { + painter.drawText(rect(), Qt::AlignCenter, text()); + } + else + { + QSize textSize(fontMetrics().size(Qt::TextSingleLine, text())); + + QSize base(size()-textSize); + + const int pad = 12; + const int iw = iconSize().width() + pad; + + QPoint pos((base.width()-iw)/2, 0); + + QRect textGeometry(pos + QPoint(0, base.height()/2), textSize); + QRect iconGeometry(pos + QPoint(0, (height()-iconSize().height())/2), iconSize()); + + if (Material::LeftIcon == d->iconPlacement) { + textGeometry.translate(iw, 0); + } else { + iconGeometry.translate(textSize.width() + pad, 0); + } + + painter.drawText(textGeometry, Qt::AlignCenter, text()); + icon().paint(&painter, iconGeometry); + } + + /* QStylePainter style(this); QStyleOptionButton option; @@ -340,6 +406,7 @@ void FlatButton::paintEvent(QPaintEvent *event) style.setOpacity(1); style.drawControl(QStyle::CE_PushButtonLabel, option); + */ #ifdef DEBUG_LAYOUT QPainter debug(this); @@ -356,7 +423,7 @@ void FlatButton::mousePressEvent(QMouseEvent *event) Q_D(FlatButton); if (Material::NoRipple == d->rippleStyle) { - return; + return QPushButton::mousePressEvent(event); } Ripple *ripple = new Ripple(Material::CenteredRipple == d->rippleStyle diff --git a/components/flatbutton.h b/components/flatbutton.h index 2ddb998..e17119c 100644 --- a/components/flatbutton.h +++ b/components/flatbutton.h @@ -7,12 +7,6 @@ class FlatButtonPrivate; -/* - * @TODO: implement checkable behavior - * - * @TODO: set default minimum height? - */ - class FlatButton : public QPushButton { Q_OBJECT @@ -31,6 +25,8 @@ public: explicit FlatButton(const QString &text, QWidget *parent = 0); ~FlatButton(); + QSize sizeHint() const Q_DECL_OVERRIDE; + void setHasFixedRippleRadius(bool value); bool hasFixedRippleRadius() const; @@ -48,6 +44,9 @@ public: void setRippleStyle(Material::RippleStyle style); Material::RippleStyle rippleStyle() const; + void setIconPlacement(Material::IconPlacement placement); + Material::IconPlacement iconPlacement() const; + void setCornerRadius(qreal radius); qreal cornerRadius() const; diff --git a/components/flatbutton_internal.cpp b/components/flatbutton_internal.cpp index 7c25766..1af9836 100644 --- a/components/flatbutton_internal.cpp +++ b/components/flatbutton_internal.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "flatbutton.h" FlatButtonDelegate::FlatButtonDelegate(FlatButton *parent) @@ -150,11 +151,19 @@ void FlatButtonDelegate::updatePalette() palette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor); button->setPalette(palette); - _normalState->assignProperty(this, "backgroundOpacity", 0); + qreal baseOpacity; + + if (button->isCheckable() && button->isChecked()) { + baseOpacity = button->peakOpacity(); + } else { + baseOpacity = 0; + } + + _normalState->assignProperty(this, "backgroundOpacity", baseOpacity); _normalState->assignProperty(this, "backgroundColor", bgColor); _normalState->assignProperty(this, "haloOpacity", 0); - _normalFocusedState->assignProperty(this, "backgroundOpacity", 0); + _normalFocusedState->assignProperty(this, "backgroundOpacity", baseOpacity); _normalFocusedState->assignProperty(this, "backgroundColor", bgColor); _normalFocusedState->assignProperty(this, "haloOpacity", button->peakOpacity()); @@ -178,6 +187,9 @@ bool FlatButtonDelegate::eventFilter(QObject *watched, QEvent *event) return true; } } + if (button->isCheckable()) { + updatePalette(); + } return QStateMachine::eventFilter(watched, event); } diff --git a/components/flatbutton_p.h b/components/flatbutton_p.h index da47160..46d8368 100644 --- a/components/flatbutton_p.h +++ b/components/flatbutton_p.h @@ -25,6 +25,7 @@ public: FlatButtonDelegate *delegate; Material::Role role; Material::RippleStyle rippleStyle; + Material::IconPlacement iconPlacement; qreal cornerRadius; Qt::BGMode bgMode; QColor textColor; diff --git a/components/menu.cpp b/components/menu.cpp index 249749b..0c45eb6 100644 --- a/components/menu.cpp +++ b/components/menu.cpp @@ -46,9 +46,13 @@ Menu::Menu(QWidget *parent) layout->setMargin(0); layout->setSpacing(0); - QSizePolicy policy; - policy.setVerticalPolicy(QSizePolicy::Maximum); - setSizePolicy(policy); + //QSizePolicy policy; + //policy.setVerticalPolicy(QSizePolicy::Maximum); + //setSizePolicy(policy); + +// QSizePolicy policy(QSizePolicy::MinimumExpanding, +// QSizePolicy::MinimumExpanding); +// setSizePolicy(policy); //QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; //effect->setBlurRadius(9); @@ -63,7 +67,7 @@ Menu::~Menu() void Menu::addMenuItem(MenuItem *item) { - _items.push_back(item); + m_items.push_back(item); layout()->addWidget(item); } @@ -74,8 +78,8 @@ void Menu::addMenuItem(const QString &text) void Menu::paintEvent(QPaintEvent *event) { + Q_UNUSED(event) + QPainter painter(this); painter.fillRect(rect(), Qt::white); - - QWidget::paintEvent(event); } diff --git a/components/menu.h b/components/menu.h index d915db0..205c0c6 100644 --- a/components/menu.h +++ b/components/menu.h @@ -13,7 +13,7 @@ public: explicit MenuItem(const QString &text, QWidget *parent = 0); ~MenuItem(); - QSize sizeHint() const; + QSize sizeHint() const Q_DECL_OVERRIDE; }; class Menu : public QWidget @@ -27,13 +27,13 @@ public: void addMenuItem(MenuItem *item); void addMenuItem(const QString &text); - inline int itemCount() const { return _items.count(); } + inline int itemCount() const { return m_items.count(); } protected: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private: - QList _items; + QList m_items; }; #endif // MENU_H diff --git a/components/sliderthumb.h b/components/sliderthumb.h index 8e28c78..e4f0943 100644 --- a/components/sliderthumb.h +++ b/components/sliderthumb.h @@ -18,7 +18,7 @@ class SliderThumb : public QWidget public: explicit SliderThumb(Slider *slider); - virutal ~SliderThumb(); + ~SliderThumb(); inline void setDiameter(qreal diameter) { diff --git a/lib/sizeproxy.cpp b/lib/sizeproxy.cpp new file mode 100644 index 0000000..3317d11 --- /dev/null +++ b/lib/sizeproxy.cpp @@ -0,0 +1,145 @@ +#include "sizeproxy.h" +#include +#include +#include +#include + +ProxyWidget2::ProxyWidget2(QWidget *source, QWidget *parent) + : QWidget(parent), + m_sourceWidget(source), + m_sx(1.0), + m_sy(1.0), + m_scaled(false) +{ + //source->installEventFilter(this); +} + +ProxyWidget2::~ProxyWidget2() +{ +} + +//QSize ProxyWidget2::sizeHint() const +//{ +// return m_sourceWidget->sizeHint(); +// //return QSize(500, 500); +//} + +bool ProxyWidget2::eventFilter(QObject *obj, QEvent *event) +{ + switch (event->type()) + { + case QEvent::UpdateLater: + //case QEvent::Move: + //case QEvent::Resize: + { + QRect rect(m_sourceWidget->geometry()); + //rect.setWidth(rect.width()*m_sx); + //rect.setHeight(rect.height()*m_sy); + setGeometry(rect); + break; + } + default: + break; + } + + return QWidget::eventFilter(obj, event); +} + +void ProxyWidget2::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + if (m_scaled) { + painter.scale(m_sx, m_sy); + } + + //qDebug() << rect(); + + //m_sourceWidget->ensurePolished(); + + //QPixmap pixmap = m_sourceWidget->grab(rect()); + + QPixmap pixmap = m_sourceWidget->grab(rect()); + painter.drawPixmap(QRect(0, 0, 50, 100), pixmap); + + //painter.drawRect(m_sourceWidget->rect()); + painter.setPen(Qt::blue); + painter.drawRect(rect().adjusted(0, 0, -1, -1)); +} + +SizeProxy::SizeProxy(QWidget *widget) + : QStackedLayout(), + m_proxy(new ProxyWidget2(widget)) +{ + addWidget(widget); + addWidget(m_proxy); + + //setCurrentIndex(0); + + //widget->setAttribute(Qt::WA_DontShowOnScreen); + + setStackingMode(QStackedLayout::StackAll); + widget->setVisible(false); +} + +SizeProxy::~SizeProxy() +{ +} + +void SizeProxy::setGeometry(const QRect &geometry) +{ + qDebug() << geometry; + + //setGeometry(500, 500); + + //QRect rect(m_sourceWidget->geometry()); + QRect rect(geometry); + //rect.setWidth(rect.width()*m_proxy->m_sx); + //rect.setHeight(rect.height()*m_proxy->m_sy); + + QStackedLayout::setGeometry(rect); +} + +void SizeProxy::setScale(qreal sx, qreal sy) +{ + const bool scaled = !qFuzzyCompare(1.0, sx) || !qFuzzyCompare(1.0, sy); + + //if (1 != currentIndex() && scaled) { + // setCurrentIndex(1); + //} else if (0 != currentIndex() && !scaled) { + // setCurrentIndex(0); + //} + + m_proxy->m_scaled = scaled; + m_proxy->m_sx = sx; + m_proxy->m_sy = sy; + m_proxy->update(); +} + +void SizeProxy::getScale(qreal *sx, qreal *sy) +{ + *sx = m_proxy->m_sx; + *sy = m_proxy->m_sy; +} + +void SizeProxy::setXScale(qreal s) +{ + setScale(s, m_proxy->m_sy); +} + +qreal SizeProxy::xScale() const +{ + return m_proxy->m_sx; +} + +void SizeProxy::setYScale(qreal s) +{ + setScale(m_proxy->m_sx, s); +} + +qreal SizeProxy::yScale() const +{ + return m_proxy->m_sy; +} diff --git a/lib/sizeproxy.h b/lib/sizeproxy.h new file mode 100644 index 0000000..9ad93f5 --- /dev/null +++ b/lib/sizeproxy.h @@ -0,0 +1,62 @@ +#ifndef SIZEPROXY_H +#define SIZEPROXY_H + +#include +#include + +class SizeProxy; + +class ProxyWidget2 : public QWidget +{ + Q_OBJECT + +public: + explicit ProxyWidget2(QWidget *source, QWidget *parent = 0); + ~ProxyWidget2(); + +// QSize sizeHint() const; + +protected: + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(ProxyWidget2) + + friend class SizeProxy; + + QWidget *const m_sourceWidget; + qreal m_sx; + qreal m_sy; + bool m_scaled; +}; + +class SizeProxy : public QStackedLayout +{ + Q_OBJECT + + Q_PROPERTY(qreal xScale WRITE setXScale READ xScale) + Q_PROPERTY(qreal yScale WRITE setYScale READ yScale) + +public: + explicit SizeProxy(QWidget *widget); + ~SizeProxy(); + + void setGeometry(const QRect &geometry); + + void setScale(qreal sx, qreal sy); + void getScale(qreal *sx, qreal *sy); + + void setXScale(qreal s); + qreal xScale() const; + + void setYScale(qreal s); + qreal yScale() const; + +private: + Q_DISABLE_COPY(SizeProxy) + + ProxyWidget2 *const m_proxy; +}; + +#endif // SIZEPROXY_H diff --git a/lib/sizeproxywidget.cpp b/lib/sizeproxywidget.cpp new file mode 100644 index 0000000..4e03b1d --- /dev/null +++ b/lib/sizeproxywidget.cpp @@ -0,0 +1,129 @@ +#include "sizeproxywidget.h" +#include +#include +#include +#include + +SizeProxyWidget::SizeProxyWidget(QWidget *source, QWidget *parent) + : QWidget(parent), + m_sourceWidget(source), + m_canvasSx(1.0), + m_canvasSy(1.0), + m_sx(1.0), + m_sy(1.0), + m_opacity(1.0) +{ + QSizePolicy policy; + policy.setHorizontalPolicy(QSizePolicy::Maximum); + policy.setVerticalPolicy(QSizePolicy::Maximum); + setSizePolicy(policy); + + //source->setParent(this, Qt::Tool); + source->setParent(this); + //source->installEventFilter(this); +} + +SizeProxyWidget::~SizeProxyWidget() +{ +} + +QSize SizeProxyWidget::sizeHint() const +{ + return m_sourceWidget->sizeHint(); +} + +void SizeProxyWidget::setCanvasXScale(qreal s) +{ + m_canvasSx = s; + update(); +} + +void SizeProxyWidget::setCanvasYScale(qreal s) +{ + m_canvasSy = s; + update(); +} + +void SizeProxyWidget::setXScale(qreal s) +{ + m_sx = s; + banan(); +} + +void SizeProxyWidget::setYScale(qreal s) +{ + m_sy = s; + banan(); +} + +void SizeProxyWidget::setOpacity(qreal opacity) +{ + m_opacity = opacity; + update(); +} + +bool SizeProxyWidget::event(QEvent *event) +{ + switch (event->type()) + { + case QEvent::Resize: + { + QPixmap pm = m_sourceWidget->grab(m_sourceWidget->geometry()); + m_pixmap = pm.scaled(static_cast(m_sourceWidget->width())*m_sx, + static_cast(m_sourceWidget->height())*m_sy, + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + break; + } + default: + break; + } + return QWidget::event(event); +} + +//bool SizeProxyWidget::eventFilter(QObject *obj, QEvent *event) +//{ +// qDebug() << event->type(); +// if (QEvent::Resize == event->type()) { +// qDebug() << size(); +// } +// if (QEvent::LayoutRequest == event->type()) { +// qDebug() << height(); +// //m_pixmap = m_sourceWidget->grab(QRect(0, 0, 300, 480)); +// } +// return QWidget::eventFilter(obj, event); +//} + +void SizeProxyWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + //painter.drawPixmap(0, 0, m_pixmap); + + //QRect r(rect()); + //r.setWidth(static_cast(width())*m_sx); + //r.setHeight(static_cast(height())*m_sy); + + //painter.setPen(Qt::green); + + //painter.setPen(Qt::NoPen); + //painter.setBrush(Qt::blue); + //painter.drawRect(rect()); + + //painter.setOpacity(m_opacity); + //painter.scale(m_sx, m_sy); + + painter.drawPixmap(0, 0, m_pixmap); +} + +void SizeProxyWidget::banan() +{ + QRect rect(m_sourceWidget->geometry()); + rect.setWidth(static_cast(rect.width())*m_sx); + rect.setHeight(static_cast(rect.height())*m_sy); + setGeometry(rect); + update(); +} diff --git a/lib/sizeproxywidget.h b/lib/sizeproxywidget.h new file mode 100644 index 0000000..637533f --- /dev/null +++ b/lib/sizeproxywidget.h @@ -0,0 +1,88 @@ +#ifndef SIZEPROXYWIDGET_H +#define SIZEPROXYWIDGET_H + +#include + +class SizeProxyWidget : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(qreal canvasXScale WRITE setCanvasXScale READ canvasXScale) + Q_PROPERTY(qreal canvasYScale WRITE setCanvasYScale READ canvasYScale) + Q_PROPERTY(qreal xScale WRITE setXScale READ xScale) + Q_PROPERTY(qreal yScale WRITE setYScale READ yScale) + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + +public: + SizeProxyWidget(QWidget *source, QWidget *parent = 0); + ~SizeProxyWidget(); + + QSize sizeHint() const Q_DECL_OVERRIDE; + + inline QRect sourceGeometry() const; + + void setCanvasXScale(qreal s); + inline qreal canvasXScale() const; + + void setCanvasYScale(qreal s); + inline qreal canvasYScale() const; + + void setXScale(qreal s); + inline qreal xScale() const; + + void setYScale(qreal s); + inline qreal yScale() const; + + void setOpacity(qreal opacity); + inline qreal opacity() 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: + Q_DISABLE_COPY(SizeProxyWidget) + + void banan(); + + QWidget *const m_sourceWidget; + QPixmap m_pixmap; + qreal m_canvasSx; + qreal m_canvasSy; + qreal m_sx; + qreal m_sy; + qreal m_opacity; +}; + +inline QRect SizeProxyWidget::sourceGeometry() const +{ + return m_sourceWidget->geometry(); +} + +inline qreal SizeProxyWidget::canvasXScale() const +{ + return m_canvasSx; +} + +inline qreal SizeProxyWidget::canvasYScale() const +{ + return m_canvasSy; +} + +inline qreal SizeProxyWidget::xScale() const +{ + return m_sx; +} + +inline qreal SizeProxyWidget::yScale() const +{ + return m_sy; +} + +inline qreal SizeProxyWidget::opacity() const +{ + return m_opacity; +} + +#endif // SIZEPROXYWIDGET_H diff --git a/lib/theme.h b/lib/theme.h index 7b69238..5379530 100644 --- a/lib/theme.h +++ b/lib/theme.h @@ -8,6 +8,11 @@ namespace Material { + enum IconPlacement { + LeftIcon, + RightIcon + }; + enum ProgressType { DeterminateProgress, IndeterminateProgress diff --git a/main.cpp b/main.cpp index b1873b1..fadc5a9 100644 --- a/main.cpp +++ b/main.cpp @@ -1,20 +1,14 @@ #include "mainwindow.h" #include -#include #include "style.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); - QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Regular.ttf"); - QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Medium.ttf"); - QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Bold.ttf"); - - QFontDatabase db; - QFont font(db.font("Roboto", "Regular", 11)); - - a.setFont(font); + //QFontDatabase db; + //QFont font(db.font("Roboto", "Regular", 11)); + //a.setFont(font); MainWindow w; w.show(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 97bf4b7..a7ed89b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,60 +1,263 @@ #include "mainwindow.h" #include #include +#include +#include +#include +#include +#include +#include #include "components/flatbutton.h" #include "components/raisedbutton.h" #include "components/drawer.h" +#include "components/menu.h" #include "lib/testrippleoverlay.h" +#include "lib/transparencyproxy.h" +#include "lib/sizeproxy.h" +#include "components/appmenu.h" +#include "xx/qtmaterialflatbutton.h" +#include "lib/sizeproxywidget.h" +#include "yy/flatbuttonsettingseditor.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { - QVBoxLayout *layout = new QVBoxLayout; - QWidget *widget = new QWidget; + FlatButtonSettingsEditor *fb = new FlatButtonSettingsEditor; + setCentralWidget(fb); - widget->setLayout(layout); - setCentralWidget(widget); -// FlatButton *button = new FlatButton; +// QWidget *widget = new QWidget; +// QVBoxLayout *layout = new QVBoxLayout; +// +// //QSizePolicy p(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding); +// //widget->setSizePolicy(p); +// +// layout->setContentsMargins(50, 0, 50, 0); +// layout->setSizeConstraint(QLayout::SetMaximumSize); +// layout->setSpacing(20); +// +// widget->setLayout(layout); +// +// layout->addStretch(1); +// +// QtMaterialFlatButton *b = new QtMaterialFlatButton; +// b->setText("Hello olleh"); +// b->setMaximumWidth(300); +// layout->addWidget(b); +// +// //b = new QtMaterialFlatButton; +// //b->setText("Hello olleh"); +// //layout->addWidget(b); +// +// setCentralWidget(widget); +// +// // ------------------------------------------- +// +// QWidget *w = new QWidget; +// QVBoxLayout *l = new QVBoxLayout; +// w->setLayout(l); +// +// QCheckBox *cb; +// QComboBox *combo; +// QLineEdit *le; +// QHBoxLayout *hl; +// +// cb = new QCheckBox; +// cb->setText("Disabled"); +// l->addWidget(cb); +// +// cb = new QCheckBox; +// cb->setText("Show halo"); +// cb->setChecked(true); +// l->addWidget(cb); +// +// cb = new QCheckBox; +// cb->setText("Transparent background"); +// cb->setChecked(true); +// l->addWidget(cb); +// +// hl = new QHBoxLayout; +// +// QLabel *lbl = new QLabel("Role"); +// hl->addWidget(lbl); +// +// combo = new QComboBox; +// combo->addItem("Default"); +// combo->addItem("Primary"); +// combo->addItem("Secondary"); +// hl->addWidget(combo); +// hl->setStretchFactor(combo, 2); +// +// l->addLayout(hl); +// +// // ------------------------------------------- +// +// layout->addWidget(w); +// layout->addStretch(1); +// +// return; +// +// +// FlatButton *fbtn; +// +// fbtn = new FlatButton("Call HQ"); +//// fbtn->setMinimumHeight(42); +//// fbtn->setIcon(QIcon("../qt-material-widgets/ic_star_black_24px.svg")); +//// fbtn->setIconSize(QSize(32, 32)); +// fbtn->setCheckable(true); +// fbtn->setChecked(false); +// fbtn->setShowHalo(false); +// fbtn->setPeakOpacity(0.3); +// layout->addWidget(fbtn); +// +// QtMaterialFlatButton *qfbtn; +// +// qfbtn = new QtMaterialFlatButton("Call HQ"); +// //qfbtn->setCheckable(true); +// //qfbtn->setChecked(false); +// //qfbtn->setShowHalo(false); +// //qfbtn->setPeakOpacity(0.3); +// layout->addWidget(qfbtn); +// +// +//// QPushButton *btn; +//// +//// btn = new QPushButton("button 1"); +//// layout->addWidget(btn); +//// +//// btn = new QPushButton("button 2"); +//// layout->addWidget(btn); +//// +//// btn = new QPushButton("button 3"); +//// layout->addWidget(btn); +//// +//// QPushButton *fbtn; +//// +//// fbtn = new FlatButton("Call HQ"); +//// fbtn->setMinimumHeight(42); +//// fbtn->setIcon(QIcon("../qt-material-widgets/ic_star_black_24px.svg")); +//// fbtn->setIconSize(QSize(32, 32)); +//// layout->addWidget(fbtn); +//// +//// fbtn = new FlatButton("button 2"); +//// layout->addWidget(fbtn); +//// +//// fbtn = new FlatButton("button 3"); +//// layout->addWidget(fbtn); +// +// widget->setParent(this); +// +//// _initMenu(); +// +// //AppMenu *am = new AppMenu; +// //layout->addWidget(am); +// +//// Menu *m = new Menu; +//// m->addMenuItem("Item 1"); +//// m->addMenuItem("Item 2"); +//// m->addMenuItem("Item 3"); +//// +//// //layout->addWidget(m); +//// +//// QPushButton *bt = new QPushButton("Helelele"); +//// +//// SizeProxyWidget *sp = new SizeProxyWidget(m); +//// layout->addWidget(sp); +//// +//// QPushButton *bt2 = new QPushButton("Keso"); +//// layout->addWidget(bt2); +// +// +// /* +// +// QVBoxLayout *layout = new QVBoxLayout; +// QWidget *widget = new QWidget; +// +// widget->setLayout(layout); +// setCentralWidget(widget); +// +// QPushButton *button = new QPushButton; +// button->setText("Hello"); +// layout->addWidget(button); +// +// Menu *menu = new Menu; +// menu->addMenuItem("Menu item #1"); +// menu->addMenuItem("Menu item #2"); +// menu->addMenuItem("Menu item #3"); +// +// //menu->setParent(widget); +// +// SizeProxy *proxy = new SizeProxy(menu); +// QWidget *widget2 = new QWidget; +// widget2->setLayout(proxy); +// widget2->setParent(widget); +// +//// QPushButton *b = new QPushButton; +// +// //TransparencyProxy *proxy = new TransparencyProxy; +// //proxy->setWidget(menu); +// ////layout->addWidget(proxy); +// +// //QWidget *widget2 = new QWidget; +// //widget2->setLayout(proxy); +// +// //widget2->setParent(this); +// +// return; +// */ +// +//// FlatButton *button = new FlatButton; +//// button->setText("Hello"); +//// +//// layout->addWidget(button); +// +// /* +// RaisedButton *button; +// +// //RaisedButton btn2(*button); +// +// button = new RaisedButton; // button->setText("Hello"); // // layout->addWidget(button); - - RaisedButton *button; - - //RaisedButton btn2(*button); - - button = new RaisedButton; - button->setText("Hello"); - - layout->addWidget(button); - - Drawer *drawer = new Drawer; - - connect(button, SIGNAL(clicked(bool)), drawer, SLOT(openDrawer())); - - drawer->setParent(this); - - QPushButton *btn1 = new QPushButton; - btn1->setText("Hello"); - - connect(btn1, SIGNAL(clicked(bool)), drawer, SLOT(openDrawer())); - - QPushButton *btn2 = new QPushButton; - btn2->setText("This is a button"); - - connect(btn2, SIGNAL(clicked(bool)), drawer, SLOT(closeDrawer())); - - layout = new QVBoxLayout; - layout->addWidget(btn1); - layout->addWidget(btn2); - layout->addStretch(); - - drawer->setDrawerLayout(layout); - - //TestRippleOverlay *overlay = new TestRippleOverlay; - //overlay->setParent(this); - +// +// // +// +// Menu *menu = new Menu; +// menu->addMenuItem("Menu item #1"); +// menu->addMenuItem("Menu item #2"); +// menu->addMenuItem("Menu item #3"); +// +// layout->addWidget(menu); +// +// // +// +// Drawer *drawer = new Drawer; +// +// connect(button, SIGNAL(clicked(bool)), drawer, SLOT(openDrawer())); +// +// drawer->setParent(this); +// +// QPushButton *btn1 = new QPushButton; +// btn1->setText("Hello"); +// +// connect(btn1, SIGNAL(clicked(bool)), drawer, SLOT(openDrawer())); +// +// QPushButton *btn2 = new QPushButton; +// btn2->setText("This is a button"); +// +// connect(btn2, SIGNAL(clicked(bool)), drawer, SLOT(closeDrawer())); +// +// layout = new QVBoxLayout; +// layout->addWidget(btn1); +// layout->addWidget(btn2); +// layout->addStretch(); +// +// drawer->setDrawerLayout(layout); +// +// //TestRippleOverlay *overlay = new TestRippleOverlay; +// //overlay->setParent(this); +// */ } MainWindow::~MainWindow() @@ -67,9 +270,60 @@ void MainWindow::paintEvent(QPaintEvent *event) QPainter painter(this); - painter.setPen(Qt::red); + painter.setPen(Qt::green); -// painter.drawRect(rect()); + painter.drawRect(rect()); +} + +void MainWindow::_initMenu() const +{ + QMenu *file = new QMenu("&File"); + + //QAction *exitAction = file->addAction("E&xit"); + + AppMenu *components = new AppMenu("&Components"); + QMenu *settings = new QMenu("&Settings"); + QMenu *examples = new QMenu("&Examples"); + QMenu *help = new QMenu("&Help"); + + components->addAction("App Bar"); + components->addAction("Avatar"); + + QMenu *buttons = new QMenu("Buttons"); + components->addMenu(buttons); + + buttons->addAction("Flat Button"); + buttons->addAction("Raised Button"); + buttons->addAction("Icon Button"); + + components->addAction("Dialog"); + + QMenu *menus = new QMenu("Menus"); + components->addMenu(menus); + + menus->addAction("Menu"); + menus->addAction("Icon Menu"); + menus->addAction("Drop Down Menu"); + + components->addAction("List"); + components->addAction("Slider"); + + QMenu *switches = new QMenu("Switches"); + components->addMenu(switches); + + switches->addAction("Checkbox"); + switches->addAction("Radio Button"); + switches->addAction("Toggle"); + + components->addAction("Table"); + components->addAction("Tabs"); + components->addAction("Text Field"); + + menuBar()->addMenu(file); + menuBar()->addMenu(components); + menuBar()->addMenu(settings); + menuBar()->addMenu(examples); + menuBar()->addMenu(help); } /* diff --git a/mainwindow.h b/mainwindow.h index 20d6fc3..10905d4 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -13,6 +13,9 @@ public: protected: void paintEvent(QPaintEvent *event); + +private: + void _initMenu() const; }; /* diff --git a/qt-material-widgets.pro b/qt-material-widgets.pro index 3cca9ab..850954a 100644 --- a/qt-material-widgets.pro +++ b/qt-material-widgets.pro @@ -75,7 +75,19 @@ SOURCES += main.cpp\ lib/transparencyproxy_internal.cpp \ components/drawer_internal.cpp \ lib/testrippleoverlay.cpp \ - lib/overlaywidget.cpp + lib/overlaywidget.cpp \ + lib/sizeproxy.cpp \ + components/collapsiblemenu.cpp \ + components/appmenu.cpp \ + xx/qtmaterialflatbutton.cpp \ + xxlib/qtmaterialrippleoverlay.cpp \ + xxlib/qtmaterialripple.cpp \ + xxlib/qtmaterialoverlaywidget.cpp \ + lib/sizeproxywidget.cpp \ + xx/qtmaterialflatbutton_internal.cpp \ + xxlib/qtmaterialstyle.cpp \ + xxlib/qtmaterialtheme.cpp \ + yy/flatbuttonsettingseditor.cpp HEADERS += mainwindow.h \ components/appbar.h \ @@ -165,7 +177,22 @@ HEADERS += mainwindow.h \ components/drawer_p.h \ components/drawer_internal.h \ lib/testrippleoverlay.h \ - lib/overlaywidget.h + lib/overlaywidget.h \ + lib/sizeproxy.h \ + components/collapsiblemenu.h \ + components/appmenu.h \ + xx/qtmaterialflatbutton.h \ + xx/qtmaterialflatbutton_p.h \ + xxlib/qtmaterialrippleoverlay.h \ + xxlib/qtmaterialripple.h \ + xxlib/qtmaterialoverlaywidget.h \ + xxlib/qtmaterialtheme.h \ + lib/sizeproxywidget.h \ + xx/qtmaterialflatbutton_internal.h \ + xxlib/qtmaterialstyle.h \ + xxlib/qtmaterialstyle_p.h \ + xxlib/qtmaterialtheme_p.h \ + yy/flatbuttonsettingseditor.h RESOURCES += \ resources.qrc diff --git a/xx/qtmaterialflatbutton.cpp b/xx/qtmaterialflatbutton.cpp new file mode 100644 index 0000000..030044c --- /dev/null +++ b/xx/qtmaterialflatbutton.cpp @@ -0,0 +1,674 @@ +#include "xx/qtmaterialflatbutton.h" +#include "xx/qtmaterialflatbutton_p.h" +#include +#include +#include +#include +#include +#include +#include +#include "xxlib/qtmaterialrippleoverlay.h" +#include "xxlib/qtmaterialripple.h" +#include "xxlib/qtmaterialstyle.h" +#include "xx/qtmaterialflatbutton_internal.h" + +/*! + * \class QtMaterialFlatButtonPrivate + * \internal + */ + +/*! + * \internal + */ +QtMaterialFlatButtonPrivate::QtMaterialFlatButtonPrivate(QtMaterialFlatButton *q) + : q_ptr(q) +{ +} + +/*! + * \internal + */ +QtMaterialFlatButtonPrivate::~QtMaterialFlatButtonPrivate() +{ +} + +/*! + * \internal + */ +void QtMaterialFlatButtonPrivate::init() +{ + Q_Q(QtMaterialFlatButton); + + rippleOverlay = new QtMaterialRippleOverlay(q); + stateMachine = new QtMaterialFlatButtonStateMachine(q); + role = XXMaterial::Default; + rippleStyle = XXMaterial::PositionedRipple; + iconPlacement = XXMaterial::LeftIcon; + overlayStyle = XXMaterial::GrayOverlay; + bgMode = Qt::TransparentMode; + fixedRippleRadius = 64; + cornerRadius = 3; + baseOpacity = 0.13; + fontSize = 10; // 10.5; + useThemeColors = true; + useFixedRippleRadius = false; + haloVisible = true; + + q->setStyle(&QtMaterialStyle::instance()); + q->setAttribute(Qt::WA_Hover); + q->setMouseTracking(true); + + QFontDatabase db; + QFont font(db.font("Roboto", "Regular", fontSize)); + font.setCapitalization(QFont::AllUppercase); + font.setStyleName("Medium"); + q->setFont(font); + + q->updateClipPath(); + rippleOverlay->setClipping(true); + + stateMachine->setupProperties(); + stateMachine->startAnimations(); +} + +/*! + * \class QtMaterialFlatButton + */ + +QtMaterialFlatButton::QtMaterialFlatButton(XXMaterial::ButtonPreset preset, QWidget *parent) + : QPushButton(parent), + d_ptr(new QtMaterialFlatButtonPrivate(this)) +{ + d_func()->init(); + + applyPreset(preset); +} + +QtMaterialFlatButton::QtMaterialFlatButton(const QString &text, XXMaterial::ButtonPreset preset, QWidget *parent) + : QPushButton(text, parent), + d_ptr(new QtMaterialFlatButtonPrivate(this)) +{ + d_func()->init(); + + applyPreset(preset); +} + +QtMaterialFlatButton::QtMaterialFlatButton(const QString &text, XXMaterial::Role role, XXMaterial::ButtonPreset preset, QWidget *parent) + : QPushButton(text, parent), + d_ptr(new QtMaterialFlatButtonPrivate(this)) +{ + d_func()->init(); + + applyPreset(preset); + setRole(role); +} + +QtMaterialFlatButton::~QtMaterialFlatButton() +{ +} + +void QtMaterialFlatButton::applyPreset(XXMaterial::ButtonPreset preset) +{ + switch (preset) + { + case XXMaterial::FlatPreset: + setOverlayStyle(XXMaterial::NoOverlay); + break; + case XXMaterial::CheckablePreset: + setOverlayStyle(XXMaterial::NoOverlay); + setCheckable(true); + setHaloVisible(false); + break; + default: + break; + } +} + +void QtMaterialFlatButton::setUseThemeColors(bool value) +{ + Q_D(QtMaterialFlatButton); + + d->useThemeColors = value; + d->stateMachine->setupProperties(); +} + +bool QtMaterialFlatButton::useThemeColors() const +{ + Q_D(const QtMaterialFlatButton); + + return d->useThemeColors; +} + +void QtMaterialFlatButton::setRole(XXMaterial::Role role) +{ + Q_D(QtMaterialFlatButton); + + d->role = role; + d->stateMachine->setupProperties(); +} + +XXMaterial::Role QtMaterialFlatButton::role() const +{ + Q_D(const QtMaterialFlatButton); + + return d->role; +} + +void QtMaterialFlatButton::setForegroundColor(const QColor &color) +{ + Q_D(QtMaterialFlatButton); + + d->foregroundColor = color; + setUseThemeColors(false); +} + +QColor QtMaterialFlatButton::foregroundColor() const +{ + Q_D(const QtMaterialFlatButton); + + if (d->useThemeColors || !d->foregroundColor.isValid()) + { + if (Qt::OpaqueMode == d->bgMode) { + return QtMaterialStyle::instance().themeColor("canvas"); + } + switch (d->role) + { + case XXMaterial::Primary: + return QtMaterialStyle::instance().themeColor("primary1"); + case XXMaterial::Secondary: + return QtMaterialStyle::instance().themeColor("accent1"); + case XXMaterial::Default: + default: + return QtMaterialStyle::instance().themeColor("text"); + } + } + return d->foregroundColor; +} + +void QtMaterialFlatButton::setBackgroundColor(const QColor &color) +{ + Q_D(QtMaterialFlatButton); + + d->backgroundColor = color; + setUseThemeColors(false); +} + +QColor QtMaterialFlatButton::backgroundColor() const +{ + Q_D(const QtMaterialFlatButton); + + if (d->useThemeColors || !d->backgroundColor.isValid()) + { + switch (d->role) + { + case XXMaterial::Primary: + return QtMaterialStyle::instance().themeColor("primary1"); + case XXMaterial::Secondary: + return QtMaterialStyle::instance().themeColor("accent1"); + case XXMaterial::Default: + default: + return QtMaterialStyle::instance().themeColor("text"); + } + } + return d->backgroundColor; +} + +void QtMaterialFlatButton::setOverlayColor(const QColor &color) +{ + Q_D(QtMaterialFlatButton); + + d->overlayColor = color; + setUseThemeColors(false); + setOverlayStyle(XXMaterial::TintedOverlay); +} + +QColor QtMaterialFlatButton::overlayColor() const +{ + Q_D(const QtMaterialFlatButton); + + if (d->useThemeColors || !d->overlayColor.isValid()) { + return foregroundColor(); + } + return d->overlayColor; +} + +void QtMaterialFlatButton::setDisabledForegroundColor(const QColor &color) +{ + Q_D(QtMaterialFlatButton); + + d->disabledColor = color; + setUseThemeColors(false); +} + +QColor QtMaterialFlatButton::disabledForegroundColor() const +{ + Q_D(const QtMaterialFlatButton); + + if (d->useThemeColors || !d->disabledColor.isValid()) { + return QtMaterialStyle::instance().themeColor("disabled"); + } else { + return d->disabledColor; + } +} + +void QtMaterialFlatButton::setDisabledBackgroundColor(const QColor &color) +{ + Q_D(QtMaterialFlatButton); + + d->disabledBackgroundColor = color; + setUseThemeColors(false); +} + +QColor QtMaterialFlatButton::disabledBackgroundColor() const +{ + Q_D(const QtMaterialFlatButton); + + if (d->useThemeColors || !d->disabledBackgroundColor.isValid()) { + return QtMaterialStyle::instance().themeColor("disabled3"); + } else { + return d->disabledBackgroundColor; + } +} + +void QtMaterialFlatButton::setFontSize(qreal size) +{ + Q_D(QtMaterialFlatButton); + + d->fontSize = size; + + QFont f(font()); + f.setPointSizeF(size); + setFont(f); + + update(); +} + +qreal QtMaterialFlatButton::fontSize() const +{ + Q_D(const QtMaterialFlatButton); + + return d->fontSize; +} + +void QtMaterialFlatButton::setHaloVisible(bool visible) +{ + Q_D(QtMaterialFlatButton); + + d->haloVisible = visible; + update(); +} + +bool QtMaterialFlatButton::isHaloVisible() const +{ + Q_D(const QtMaterialFlatButton); + + return d->haloVisible; +} + +void QtMaterialFlatButton::setOverlayStyle(XXMaterial::OverlayStyle style) +{ + Q_D(QtMaterialFlatButton); + + d->overlayStyle = style; + update(); +} + +XXMaterial::OverlayStyle QtMaterialFlatButton::overlayStyle() const +{ + Q_D(const QtMaterialFlatButton); + + return d->overlayStyle; +} + +void QtMaterialFlatButton::setRippleStyle(XXMaterial::RippleStyle style) +{ + Q_D(QtMaterialFlatButton); + + d->rippleStyle = style; +} + +XXMaterial::RippleStyle QtMaterialFlatButton::rippleStyle() const +{ + Q_D(const QtMaterialFlatButton); + + return d->rippleStyle; +} + +void QtMaterialFlatButton::setIconPlacement(XXMaterial::ButtonIconPlacement placement) +{ + Q_D(QtMaterialFlatButton); + + d->iconPlacement = placement; + update(); +} + +XXMaterial::ButtonIconPlacement QtMaterialFlatButton::iconPlacement() const +{ + Q_D(const QtMaterialFlatButton); + + return d->iconPlacement; +} + +void QtMaterialFlatButton::setCornerRadius(qreal radius) +{ + Q_D(QtMaterialFlatButton); + + d->cornerRadius = radius; + updateClipPath(); + update(); +} + +qreal QtMaterialFlatButton::cornerRadius() const +{ + Q_D(const QtMaterialFlatButton); + + return d->cornerRadius; +} + +void QtMaterialFlatButton::setBackgroundMode(Qt::BGMode mode) +{ + Q_D(QtMaterialFlatButton); + + d->bgMode = mode; + d->stateMachine->setupProperties(); +} + +Qt::BGMode QtMaterialFlatButton::backgroundMode() const +{ + Q_D(const QtMaterialFlatButton); + + return d->bgMode; +} + +void QtMaterialFlatButton::setBaseOpacity(qreal opacity) +{ + Q_D(QtMaterialFlatButton); + + d->baseOpacity = opacity; + d->stateMachine->setupProperties(); +} + +qreal QtMaterialFlatButton::baseOpacity() const +{ + Q_D(const QtMaterialFlatButton); + + return d->baseOpacity; +} + +void QtMaterialFlatButton::setCheckable(bool value) +{ + Q_D(QtMaterialFlatButton); + + d->stateMachine->updateCheckedStatus(); + d->stateMachine->setCheckedOverlayProgress(0); + + QPushButton::setCheckable(value); +} + +/*! + * \reimp + */ +QSize QtMaterialFlatButton::sizeHint() const +{ + ensurePolished(); + + QSize label(fontMetrics().size(Qt::TextSingleLine, text())); + + int w = 20 + label.width(); + int h = label.height(); + if (!icon().isNull()) { + w += iconSize().width() + QtMaterialFlatButton::IconPadding; + h = qMax(h, iconSize().height()); + } + return QSize(w, 20 + h); +} + +/*! + * \reimp + */ +void QtMaterialFlatButton::checkStateSet() +{ + Q_D(QtMaterialFlatButton); + + d->stateMachine->updateCheckedStatus(); + + QPushButton::checkStateSet(); +} + +/*! + * \reimp + */ +void QtMaterialFlatButton::mousePressEvent(QMouseEvent *event) +{ + Q_D(QtMaterialFlatButton); + + if (XXMaterial::NoRipple != d->rippleStyle) + { + QPoint pos; + qreal radiusEndValue; + + if (XXMaterial::CenteredRipple == d->rippleStyle) { + pos = rect().center(); + } else { + pos = event->pos(); + } + + if (d->useFixedRippleRadius) { + radiusEndValue = d->fixedRippleRadius; + } else { + radiusEndValue = static_cast(width())/2; + } + + QtMaterialRipple *ripple = new QtMaterialRipple(pos); + + ripple->setRadiusEndValue(radiusEndValue); + ripple->setOpacityStartValue(0.35); + ripple->setColor(foregroundColor()); + ripple->radiusAnimation()->setDuration(600); + ripple->opacityAnimation()->setDuration(1300); + + d->rippleOverlay->addRipple(ripple); + } + + QPushButton::mousePressEvent(event); +} + +/*! + * \reimp + */ +void QtMaterialFlatButton::mouseReleaseEvent(QMouseEvent *event) +{ + Q_D(QtMaterialFlatButton); + + QPushButton::mouseReleaseEvent(event); + + d->stateMachine->updateCheckedStatus(); +} + +void QtMaterialFlatButton::resizeEvent(QResizeEvent *event) +{ + QPushButton::resizeEvent(event); + + updateClipPath(); +} + +/*! + * \reimp + */ +void QtMaterialFlatButton::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + Q_D(QtMaterialFlatButton); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + const qreal cr = d->cornerRadius; + + QPainterPath path; + path.addRoundedRect(rect(), cr, cr); + + painter.setClipPath(path); + painter.setClipping(true); + + paintBackground(&painter); + paintHalo(&painter); + paintForeground(&painter); +} + +/*! + * \internal + */ +void QtMaterialFlatButton::paintBackground(QPainter *painter) +{ + Q_D(QtMaterialFlatButton); + + const qreal overlayOpacity = d->stateMachine->overlayOpacity(); + const qreal checkedProgress = d->stateMachine->checkedOverlayProgress(); + + if (Qt::OpaqueMode == d->bgMode) { + QBrush brush; + brush.setStyle(Qt::SolidPattern); + if (isEnabled()) { + brush.setColor(backgroundColor()); + } else { + brush.setColor(disabledBackgroundColor()); + } + painter->setOpacity(1); + painter->setBrush(brush); + painter->setPen(Qt::NoPen); + painter->drawRect(rect()); + } + + QBrush brush; + brush.setStyle(Qt::SolidPattern); + painter->setPen(Qt::NoPen); + + if (!isEnabled()) { + return; + } + + if ((XXMaterial::NoOverlay != d->overlayStyle) && (overlayOpacity > 0)) { + if (XXMaterial::TintedOverlay == d->overlayStyle) { + brush.setColor(overlayColor()); + } else { + brush.setColor(Qt::gray); + } + painter->setOpacity(overlayOpacity); + painter->setBrush(brush); + painter->drawRect(rect()); + } + + if (isCheckable() && checkedProgress > 0) { + const qreal q = Qt::TransparentMode == d->bgMode ? 0.45 : 0.7; + brush.setColor(foregroundColor()); + painter->setOpacity(q*checkedProgress); + painter->setBrush(brush); + QRect r(rect()); + r.setHeight(static_cast(r.height())*checkedProgress); + painter->drawRect(r); + } +} + +/*! + * \internal + */ +void QtMaterialFlatButton::paintHalo(QPainter *painter) +{ + Q_D(QtMaterialFlatButton); + + if (!d->haloVisible) { + return; + } + + const qreal opacity = d->stateMachine->haloOpacity(); + const qreal s = d->stateMachine->haloScaleFactor()*d->stateMachine->haloSize(); + const qreal radius = static_cast(width())*s; + + if (isEnabled() && opacity > 0) { + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(foregroundColor()); + painter->setOpacity(opacity); + painter->setBrush(brush); + painter->setPen(Qt::NoPen); + const QPointF center = rect().center(); + painter->drawEllipse(center, radius, radius); + } +} + +#define COLOR_INTERPOLATE(CH) (1-progress)*source.CH() + progress*dest.CH() + +/*! + * \internal + */ +void QtMaterialFlatButton::paintForeground(QPainter *painter) +{ + Q_D(QtMaterialFlatButton); + + painter->setOpacity(1); + painter->setClipping(false); + + if (isEnabled()) { + painter->setPen(foregroundColor()); + const qreal progress = d->stateMachine->checkedOverlayProgress(); + if (isCheckable() && progress > 0) { + QColor source = foregroundColor(); + QColor dest = Qt::TransparentMode == d->bgMode ? Qt::white + : backgroundColor(); + if (qFuzzyCompare(1, progress)) { + painter->setPen(dest); + } else { + painter->setPen(QColor(COLOR_INTERPOLATE(red), + COLOR_INTERPOLATE(green), + COLOR_INTERPOLATE(blue), + COLOR_INTERPOLATE(alpha))); + } + } + } else { + painter->setPen(disabledForegroundColor()); + } + + if (icon().isNull()) { + painter->drawText(rect(), Qt::AlignCenter, text()); + return; + } + + QSize textSize(fontMetrics().size(Qt::TextSingleLine, text())); + QSize base(size()-textSize); + + const int iw = iconSize().width() + IconPadding; + QPoint pos((base.width()-iw)/2, 0); + + QRect textGeometry(pos + QPoint(0, base.height()/2), textSize); + QRect iconGeometry(pos + QPoint(0, (height()-iconSize().height())/2), iconSize()); + + if (XXMaterial::LeftIcon == d->iconPlacement) { + textGeometry.translate(iw, 0); + } else { + iconGeometry.translate(textSize.width() + IconPadding, 0); + } + + painter->drawText(textGeometry, Qt::AlignCenter, text()); + + QPixmap pixmap = icon().pixmap(iconSize()); + QPainter icon(&pixmap); + icon.setCompositionMode(QPainter::CompositionMode_SourceIn); + icon.fillRect(pixmap.rect(), painter->pen().color()); + painter->drawPixmap(iconGeometry, pixmap); +} + +/*! + * \internal + */ +void QtMaterialFlatButton::updateClipPath() +{ + Q_D(QtMaterialFlatButton); + + const qreal radius = d->cornerRadius; + + QPainterPath path; + path.addRoundedRect(rect(), radius, radius); + d->rippleOverlay->setClipPath(path); +} diff --git a/xx/qtmaterialflatbutton.h b/xx/qtmaterialflatbutton.h new file mode 100644 index 0000000..9812737 --- /dev/null +++ b/xx/qtmaterialflatbutton.h @@ -0,0 +1,102 @@ +#ifndef QTMATERIALFLATBUTTON_H +#define QTMATERIALFLATBUTTON_H + +#include +#include +#include "xxlib/qtmaterialtheme.h" + +class QtMaterialFlatButtonPrivate; + +class QtMaterialFlatButton : public QPushButton +{ + Q_OBJECT + + Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor) + Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor) + Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ disabledForegroundColor) + Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ disabledBackgroundColor) + Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize) + + enum { + IconPadding = 12 + }; + +public: + explicit QtMaterialFlatButton(XXMaterial::ButtonPreset preset = XXMaterial::FlatPreset, QWidget *parent = 0); + explicit QtMaterialFlatButton(const QString &text, XXMaterial::ButtonPreset preset = XXMaterial::FlatPreset, QWidget *parent = 0); + QtMaterialFlatButton(const QString &text, XXMaterial::Role role, XXMaterial::ButtonPreset preset = XXMaterial::FlatPreset, QWidget *parent = 0); + ~QtMaterialFlatButton(); + + virtual void applyPreset(XXMaterial::ButtonPreset preset); + + void setUseThemeColors(bool value); + bool useThemeColors() const; + + void setRole(XXMaterial::Role role); + XXMaterial::Role role() const; + + void setForegroundColor(const QColor &color); + QColor foregroundColor() const; + + void setBackgroundColor(const QColor &color); + QColor backgroundColor() const; + + void setOverlayColor(const QColor &color); + QColor overlayColor() const; + + void setDisabledForegroundColor(const QColor &color); + QColor disabledForegroundColor() const; + + void setDisabledBackgroundColor(const QColor &color); + QColor disabledBackgroundColor() const; + + void setFontSize(qreal size); + qreal fontSize() const; + + void setHaloVisible(bool visible); + bool isHaloVisible() const; + + void setOverlayStyle(XXMaterial::OverlayStyle style); + XXMaterial::OverlayStyle overlayStyle() const; + + void setRippleStyle(XXMaterial::RippleStyle style); + XXMaterial::RippleStyle rippleStyle() const; + + void setIconPlacement(XXMaterial::ButtonIconPlacement placement); + XXMaterial::ButtonIconPlacement iconPlacement() const; + + void setCornerRadius(qreal radius); + qreal cornerRadius() const; + + void setBackgroundMode(Qt::BGMode mode); + Qt::BGMode backgroundMode() const; + + void setBaseOpacity(qreal opacity); + qreal baseOpacity() const; + + void setCheckable(bool value); + + QSize sizeHint() const Q_DECL_OVERRIDE; + +protected: + void checkStateSet() Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + void paintBackground(QPainter *painter); + void paintHalo(QPainter *painter); + void paintForeground(QPainter *painter); + + void updateClipPath(); + + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialFlatButton) + Q_DECLARE_PRIVATE(QtMaterialFlatButton) +}; + +#endif // QTMATERIALFLATBUTTON_H diff --git a/xx/qtmaterialflatbutton_internal.cpp b/xx/qtmaterialflatbutton_internal.cpp new file mode 100644 index 0000000..ee5ecca --- /dev/null +++ b/xx/qtmaterialflatbutton_internal.cpp @@ -0,0 +1,235 @@ +#include "xx/qtmaterialflatbutton_internal.h" +#include +#include +#include +#include +#include +#include "xx/qtmaterialflatbutton.h" + +/*! + * \class QtMaterialFlatButtonStateMachine + * \internal + */ + +QtMaterialFlatButtonStateMachine::QtMaterialFlatButtonStateMachine(QtMaterialFlatButton *parent) + : QStateMachine(parent), + m_button(parent), + m_topLevelState(new QState(QState::ParallelStates)), + m_configState(new QState(m_topLevelState)), + m_checkableState(new QState(m_topLevelState)), + m_checkedState(new QState(m_checkableState)), + m_uncheckedState(new QState(m_checkableState)), + m_neutralState(new QState(m_configState)), + m_neutralFocusedState(new QState(m_configState)), + m_hoveredState(new QState(m_configState)), + m_hoveredFocusedState(new QState(m_configState)), + m_pressedState(new QState(m_configState)), + m_haloAnimation(new QSequentialAnimationGroup(this)), + m_overlayOpacity(0), + m_checkedOverlayProgress(parent->isChecked() ? 1 : 0), + m_haloOpacity(0), + m_haloSize(0.8), + m_haloScaleFactor(1), + m_wasChecked(false) +{ + Q_ASSERT(parent); + + parent->installEventFilter(this); + + m_configState->setInitialState(m_neutralState); + addState(m_topLevelState); + setInitialState(m_topLevelState); + + m_checkableState->setInitialState(parent->isChecked() ? m_checkedState + : m_uncheckedState); + QSignalTransition *transition; + QPropertyAnimation *animation; + + transition = new QSignalTransition(this, SIGNAL(buttonChecked())); + transition->setTargetState(m_checkedState); + m_uncheckedState->addTransition(transition); + + animation = new QPropertyAnimation(this, "checkedOverlayProgress", this); + animation->setDuration(200); + transition->addAnimation(animation); + + transition = new QSignalTransition(this, SIGNAL(buttonUnchecked())); + transition->setTargetState(m_uncheckedState); + m_checkedState->addTransition(transition); + + animation = new QPropertyAnimation(this, "checkedOverlayProgress", this); + animation->setDuration(200); + transition->addAnimation(animation); + + addTransition(m_button, QEvent::FocusIn, m_neutralState, m_neutralFocusedState); + addTransition(m_button, QEvent::FocusOut, m_neutralFocusedState, m_neutralState); + addTransition(m_button, QEvent::Enter, m_neutralState, m_hoveredState); + addTransition(m_button, QEvent::Leave, m_hoveredState, m_neutralState); + addTransition(m_button, QEvent::Enter, m_neutralFocusedState, m_hoveredFocusedState); + addTransition(m_button, QEvent::Leave, m_hoveredFocusedState, m_neutralFocusedState); + addTransition(m_button, QEvent::FocusIn, m_hoveredState, m_hoveredFocusedState); + addTransition(m_button, QEvent::FocusOut, m_hoveredFocusedState, m_hoveredState); + addTransition(this, SIGNAL(buttonPressed()), m_hoveredState, m_pressedState); + addTransition(m_button, QEvent::Leave, m_pressedState, m_neutralFocusedState); + addTransition(m_button, QEvent::FocusOut, m_pressedState, m_hoveredState); + + m_neutralState->assignProperty(this, "haloSize", 0); + m_neutralFocusedState->assignProperty(this, "haloSize", 0.7); + m_hoveredState->assignProperty(this, "haloSize", 0); + m_pressedState->assignProperty(this, "haloSize", 4); + m_hoveredFocusedState->assignProperty(this, "haloSize", 0.7); + + QPropertyAnimation *grow = new QPropertyAnimation(this); + QPropertyAnimation *shrink = new QPropertyAnimation(this); + + grow->setTargetObject(this); + grow->setPropertyName("haloScaleFactor"); + grow->setStartValue(0.56); + grow->setEndValue(0.63); + grow->setEasingCurve(QEasingCurve::InOutSine); + grow->setDuration(840); + + shrink->setTargetObject(this); + shrink->setPropertyName("haloScaleFactor"); + shrink->setStartValue(0.63); + shrink->setEndValue(0.56); + shrink->setEasingCurve(QEasingCurve::InOutSine); + shrink->setDuration(840); + + m_haloAnimation->addAnimation(grow); + m_haloAnimation->addAnimation(shrink); + m_haloAnimation->setLoopCount(-1); +} + +QtMaterialFlatButtonStateMachine::~QtMaterialFlatButtonStateMachine() +{ +} + +void QtMaterialFlatButtonStateMachine::setOverlayOpacity(qreal opacity) +{ + m_overlayOpacity = opacity; + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::setCheckedOverlayProgress(qreal opacity) +{ + m_checkedOverlayProgress = opacity; + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::setHaloOpacity(qreal opacity) +{ + m_haloOpacity = opacity; + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::setHaloSize(qreal size) +{ + m_haloSize = size; + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::setHaloScaleFactor(qreal factor) +{ + m_haloScaleFactor = factor; + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::startAnimations() +{ + m_haloAnimation->start(); + start(); +} + +void QtMaterialFlatButtonStateMachine::setupProperties() +{ + QColor overlayColor; + + if (Qt::TransparentMode == m_button->backgroundMode()) { + overlayColor = m_button->backgroundColor(); + } else { + overlayColor = m_button->foregroundColor(); + } + + const qreal baseOpacity = m_button->baseOpacity(); + + m_neutralState->assignProperty(this, "overlayOpacity", 0); + m_neutralState->assignProperty(this, "haloOpacity", 0); + m_neutralFocusedState->assignProperty(this, "overlayOpacity", 0); + m_neutralFocusedState->assignProperty(this, "haloOpacity", baseOpacity); + m_hoveredState->assignProperty(this, "overlayOpacity", baseOpacity); + m_hoveredState->assignProperty(this, "haloOpacity", 0); + m_hoveredFocusedState->assignProperty(this, "overlayOpacity", baseOpacity); + m_hoveredFocusedState->assignProperty(this, "haloOpacity", baseOpacity); + m_pressedState->assignProperty(this, "overlayOpacity", baseOpacity); + m_pressedState->assignProperty(this, "haloOpacity", 0); + m_checkedState->assignProperty(this, "checkedOverlayProgress", 1); + m_uncheckedState->assignProperty(this, "checkedOverlayProgress", 0); + + m_button->update(); +} + +void QtMaterialFlatButtonStateMachine::updateCheckedStatus() +{ + const bool checked = m_button->isChecked(); + if (m_wasChecked != checked) { + m_wasChecked = checked; + if (checked) { + emit buttonChecked(); + } else { + emit buttonUnchecked(); + } + } +} + +bool QtMaterialFlatButtonStateMachine::eventFilter(QObject *watched, QEvent *event) +{ + if (QEvent::FocusIn == event->type()) { + QFocusEvent *focusEvent = static_cast(event); + if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) { + emit buttonPressed(); + return true; + } + } + return QStateMachine::eventFilter(watched, event); +} + +void QtMaterialFlatButtonStateMachine::addTransition(QObject *object, + const char *signal, + QState *fromState, + QState *toState) +{ + addTransition(new QSignalTransition(object, signal), fromState, toState); +} + +void QtMaterialFlatButtonStateMachine::addTransition(QObject *object, + QEvent::Type eventType, + QState *fromState, + QState *toState) +{ + addTransition(new QEventTransition(object, eventType), fromState, toState); +} + +void QtMaterialFlatButtonStateMachine::addTransition(QAbstractTransition *transition, + QState *fromState, + QState *toState) +{ + transition->setTargetState(toState); + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(this, "overlayOpacity", this); + animation->setDuration(150); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(this, "haloOpacity", this); + animation->setDuration(170); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(this, "haloSize", this); + animation->setDuration(350); + animation->setEasingCurve(QEasingCurve::OutCubic); + transition->addAnimation(animation); + + fromState->addTransition(transition); +} diff --git a/xx/qtmaterialflatbutton_internal.h b/xx/qtmaterialflatbutton_internal.h new file mode 100644 index 0000000..82449cd --- /dev/null +++ b/xx/qtmaterialflatbutton_internal.h @@ -0,0 +1,104 @@ +#ifndef QTMATERIALFLATBUTTON_INTERNAL_H +#define QTMATERIALFLATBUTTON_INTERNAL_H + +#include +#include + +class QtMaterialFlatButton; +class QSequentialAnimationGroup; + +class QtMaterialFlatButtonStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity) + Q_PROPERTY(qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress) + Q_PROPERTY(qreal haloOpacity WRITE setHaloOpacity READ haloOpacity) + Q_PROPERTY(qreal haloSize WRITE setHaloSize READ haloSize) + Q_PROPERTY(qreal haloScaleFactor WRITE setHaloScaleFactor READ haloScaleFactor) + +public: + explicit QtMaterialFlatButtonStateMachine(QtMaterialFlatButton *parent); + ~QtMaterialFlatButtonStateMachine(); + + void setOverlayOpacity(qreal opacity); + inline qreal overlayOpacity() const; + + void setCheckedOverlayProgress(qreal opacity); + inline qreal checkedOverlayProgress() const; + + void setHaloOpacity(qreal opacity); + inline qreal haloOpacity() const; + + void setHaloSize(qreal size); + inline qreal haloSize() const; + + void setHaloScaleFactor(qreal factor); + inline qreal haloScaleFactor() const; + + void startAnimations(); + void setupProperties(); + void updateCheckedStatus(); + +signals: + void buttonPressed(); + void buttonChecked(); + void buttonUnchecked(); + +protected: + bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialFlatButtonStateMachine) + + void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState); + void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState); + void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState); + + QtMaterialFlatButton *const m_button; + QState *const m_topLevelState; + QState *const m_configState; + QState *const m_checkableState; + QState *const m_checkedState; + QState *const m_uncheckedState; + QState *const m_neutralState; + QState *const m_neutralFocusedState; + QState *const m_hoveredState; + QState *const m_hoveredFocusedState; + QState *const m_pressedState; + QSequentialAnimationGroup + *const m_haloAnimation; + qreal m_overlayOpacity; + qreal m_checkedOverlayProgress; + qreal m_haloOpacity; + qreal m_haloSize; + qreal m_haloScaleFactor; + bool m_wasChecked; +}; + +inline qreal QtMaterialFlatButtonStateMachine::overlayOpacity() const +{ + return m_overlayOpacity; +} + +inline qreal QtMaterialFlatButtonStateMachine::checkedOverlayProgress() const +{ + return m_checkedOverlayProgress; +} + +inline qreal QtMaterialFlatButtonStateMachine::haloOpacity() const +{ + return m_haloOpacity; +} + +inline qreal QtMaterialFlatButtonStateMachine::haloSize() const +{ + return m_haloSize; +} + +inline qreal QtMaterialFlatButtonStateMachine::haloScaleFactor() const +{ + return m_haloScaleFactor; +} + +#endif // QTMATERIALFLATBUTTON_INTERNAL_H diff --git a/xx/qtmaterialflatbutton_p.h b/xx/qtmaterialflatbutton_p.h new file mode 100644 index 0000000..b89446d --- /dev/null +++ b/xx/qtmaterialflatbutton_p.h @@ -0,0 +1,45 @@ +#ifndef QTMATERIALFLATBUTTON_P_H +#define QTMATERIALFLATBUTTON_P_H + +#include +#include +#include "xxlib/qtmaterialtheme.h" + +class QtMaterialFlatButton; +class QtMaterialRippleOverlay; +class QtMaterialFlatButtonStateMachine; + +class QtMaterialFlatButtonPrivate +{ + Q_DISABLE_COPY(QtMaterialFlatButtonPrivate) + Q_DECLARE_PUBLIC(QtMaterialFlatButton) + +public: + QtMaterialFlatButtonPrivate(QtMaterialFlatButton *q); + virtual ~QtMaterialFlatButtonPrivate(); + + void init(); + + QtMaterialFlatButton *const q_ptr; + QtMaterialRippleOverlay *rippleOverlay; + QtMaterialFlatButtonStateMachine *stateMachine; + XXMaterial::Role role; + XXMaterial::RippleStyle rippleStyle; + XXMaterial::ButtonIconPlacement iconPlacement; + XXMaterial::OverlayStyle overlayStyle; + Qt::BGMode bgMode; + QColor backgroundColor; + QColor foregroundColor; + QColor overlayColor; + QColor disabledColor; + QColor disabledBackgroundColor; + qreal fixedRippleRadius; + qreal cornerRadius; + qreal baseOpacity; + qreal fontSize; + bool useThemeColors; + bool useFixedRippleRadius; + bool haloVisible; +}; + +#endif // QTMATERIALFLATBUTTON_P_H diff --git a/xxlib/qtmaterialoverlaywidget.cpp b/xxlib/qtmaterialoverlaywidget.cpp new file mode 100644 index 0000000..cebdad1 --- /dev/null +++ b/xxlib/qtmaterialoverlaywidget.cpp @@ -0,0 +1,72 @@ +#include "qtmaterialoverlaywidget.h" +#include + +/*! + * \class QtMaterialOverlayWidget + * \internal + */ + +QtMaterialOverlayWidget::QtMaterialOverlayWidget(QWidget *parent) + : QWidget(parent) +{ + if (parent) { + parent->installEventFilter(this); + } +} + +QtMaterialOverlayWidget::~QtMaterialOverlayWidget() +{ +} + +/*! + * \reimp + */ +bool QtMaterialOverlayWidget::event(QEvent *event) +{ + if (!parent()) { + return QWidget::event(event); + } + switch (event->type()) + { + case QEvent::ParentChange: + { + parent()->installEventFilter(this); + setGeometry(overlayGeometry()); + break; + } + case QEvent::ParentAboutToChange: + { + parent()->removeEventFilter(this); + break; + } + default: + break; + } + return QWidget::event(event); +} + +/*! + * \reimp + */ +bool QtMaterialOverlayWidget::eventFilter(QObject *obj, QEvent *event) +{ + switch (event->type()) + { + case QEvent::Move: + case QEvent::Resize: + setGeometry(overlayGeometry()); + break; + default: + break; + } + return QWidget::eventFilter(obj, event); +} + +QRect QtMaterialOverlayWidget::overlayGeometry() const +{ + QWidget *widget = parentWidget(); + if (!widget) { + return QRect(); + } + return widget->rect(); +} diff --git a/xxlib/qtmaterialoverlaywidget.h b/xxlib/qtmaterialoverlaywidget.h new file mode 100644 index 0000000..ac108cc --- /dev/null +++ b/xxlib/qtmaterialoverlaywidget.h @@ -0,0 +1,24 @@ +#ifndef QTMATERIALOVERLAYWIDGET_H +#define QTMATERIALOVERLAYWIDGET_H + +#include + +class QtMaterialOverlayWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QtMaterialOverlayWidget(QWidget *parent = 0); + ~QtMaterialOverlayWidget(); + +protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; + + virtual QRect overlayGeometry() const; + +private: + Q_DISABLE_COPY(QtMaterialOverlayWidget) +}; + +#endif // QTMATERIALOVERLAYWIDGET_H diff --git a/xxlib/qtmaterialripple.cpp b/xxlib/qtmaterialripple.cpp new file mode 100644 index 0000000..c73a376 --- /dev/null +++ b/xxlib/qtmaterialripple.cpp @@ -0,0 +1,119 @@ +#include "qtmaterialripple.h" +#include "xxlib/qtmaterialrippleoverlay.h" + +/*! + * \class QtMaterialRipple + * \internal + */ + +QtMaterialRipple::QtMaterialRipple(const QPoint ¢er, QObject *parent) + : QParallelAnimationGroup(parent), + m_overlay(0), + m_radiusAnimation(animate("radius")), + m_opacityAnimation(animate("opacity")), + m_radius(0), + m_opacity(0), + m_center(center) +{ + init(); +} + +QtMaterialRipple::QtMaterialRipple(const QPoint ¢er, + QtMaterialRippleOverlay *overlay, + QObject *parent) + : QParallelAnimationGroup(parent), + m_overlay(overlay), + m_radiusAnimation(animate("radius")), + m_opacityAnimation(animate("opacity")), + m_radius(0), + m_opacity(0), + m_center(center) +{ + init(); +} + +QtMaterialRipple::~QtMaterialRipple() +{ +} + +void QtMaterialRipple::setRadius(qreal radius) +{ + Q_ASSERT(m_overlay); + + if (m_radius == radius) { + return; + } + m_radius = radius; + m_overlay->update(); +} + +void QtMaterialRipple::setOpacity(qreal opacity) +{ + Q_ASSERT(m_overlay); + + if (m_opacity == opacity) { + return; + } + m_opacity = opacity; + m_overlay->update(); +} + +void QtMaterialRipple::setColor(const QColor &color) +{ + if (m_brush.color() == color) { + return; + } + m_brush.setColor(color); + + if (m_overlay) { + m_overlay->update(); + } +} + +void QtMaterialRipple::setBrush(const QBrush &brush) +{ + m_brush = brush; + + if (m_overlay) { + m_overlay->update(); + } +} + +void QtMaterialRipple::destroy() +{ + Q_ASSERT(m_overlay); + + m_overlay->removeRipple(this); +} + +/*! + * \internal + */ +QPropertyAnimation *QtMaterialRipple::animate(const QByteArray &property, + const QEasingCurve &easing, + int duration) +{ + QPropertyAnimation *animation = new QPropertyAnimation; + animation->setTargetObject(this); + animation->setPropertyName(property); + animation->setEasingCurve(easing); + animation->setDuration(duration); + addAnimation(animation); + return animation; +} + +/*! + * \internal + */ +void QtMaterialRipple::init() +{ + setOpacityStartValue(0.5); + setOpacityEndValue(0); + setRadiusStartValue(0); + setRadiusEndValue(300); + + m_brush.setColor(Qt::black); + m_brush.setStyle(Qt::SolidPattern); + + connect(this, SIGNAL(finished()), this, SLOT(destroy())); +} diff --git a/xxlib/qtmaterialripple.h b/xxlib/qtmaterialripple.h new file mode 100644 index 0000000..d263c76 --- /dev/null +++ b/xxlib/qtmaterialripple.h @@ -0,0 +1,136 @@ +#ifndef QTMATERIALRIPPLE_H +#define QTMATERIALRIPPLE_H + +#include +#include +#include +#include +#include + +class QtMaterialRippleOverlay; + +class QtMaterialRipple : public QParallelAnimationGroup +{ + Q_OBJECT + + Q_PROPERTY(qreal radius WRITE setRadius READ radius) + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + +public: + explicit QtMaterialRipple(const QPoint ¢er, QObject *parent = 0); + QtMaterialRipple(const QPoint ¢er, QtMaterialRippleOverlay *overlay, QObject *parent = 0); + ~QtMaterialRipple(); + + inline void setOverlay(QtMaterialRippleOverlay *overlay); + + void setRadius(qreal radius); + inline qreal radius() const; + + void setOpacity(qreal opacity); + inline qreal opacity() const; + + void setColor(const QColor &color); + inline QColor color() const; + + void setBrush(const QBrush &brush); + inline QBrush brush() const; + + inline QPoint center() const; + + inline QPropertyAnimation *radiusAnimation() const; + inline QPropertyAnimation *opacityAnimation() const; + + inline void setOpacityStartValue(qreal value); + inline void setOpacityEndValue(qreal value); + inline void setRadiusStartValue(qreal value); + inline void setRadiusEndValue(qreal value); + inline void setDuration(int msecs); + +protected slots: + void destroy(); + +private: + Q_DISABLE_COPY(QtMaterialRipple) + + QPropertyAnimation *animate(const QByteArray &property, + const QEasingCurve &easing = QEasingCurve::OutQuad, + int duration = 800); + + void init(); + + QtMaterialRippleOverlay *m_overlay; + QPropertyAnimation *const m_radiusAnimation; + QPropertyAnimation *const m_opacityAnimation; + qreal m_radius; + qreal m_opacity; + QPoint m_center; + QBrush m_brush; +}; + +inline void QtMaterialRipple::setOverlay(QtMaterialRippleOverlay *overlay) +{ + m_overlay = overlay; +} + +inline qreal QtMaterialRipple::radius() const +{ + return m_radius; +} + +inline qreal QtMaterialRipple::opacity() const +{ + return m_opacity; +} + +inline QColor QtMaterialRipple::color() const +{ + return m_brush.color(); +} + +inline QBrush QtMaterialRipple::brush() const +{ + return m_brush; +} + +inline QPoint QtMaterialRipple::center() const +{ + return m_center; +} + +inline QPropertyAnimation *QtMaterialRipple::radiusAnimation() const +{ + return m_radiusAnimation; +} + +inline QPropertyAnimation *QtMaterialRipple::opacityAnimation() const +{ + return m_opacityAnimation; +} + +inline void QtMaterialRipple::setOpacityStartValue(qreal value) +{ + m_opacityAnimation->setStartValue(value); +} + +inline void QtMaterialRipple::setOpacityEndValue(qreal value) +{ + m_opacityAnimation->setEndValue(value); +} + +inline void QtMaterialRipple::setRadiusStartValue(qreal value) +{ + m_radiusAnimation->setStartValue(value); +} + +inline void QtMaterialRipple::setRadiusEndValue(qreal value) +{ + m_radiusAnimation->setEndValue(value); +} + +inline void QtMaterialRipple::setDuration(int msecs) +{ + m_radiusAnimation->setDuration(msecs); + m_opacityAnimation->setDuration(msecs); +} + +#endif // QTMATERIALRIPPLE_H diff --git a/xxlib/qtmaterialrippleoverlay.cpp b/xxlib/qtmaterialrippleoverlay.cpp new file mode 100644 index 0000000..5f97c38 --- /dev/null +++ b/xxlib/qtmaterialrippleoverlay.cpp @@ -0,0 +1,69 @@ +#include "qtmaterialrippleoverlay.h" +#include +#include "xxlib/qtmaterialripple.h" + +/*! + * \class QtMaterialRippleOverlay + * \internal + */ + +QtMaterialRippleOverlay::QtMaterialRippleOverlay(QWidget *parent) + : QtMaterialOverlayWidget(parent), + m_useClip(false) +{ +} + +QtMaterialRippleOverlay::~QtMaterialRippleOverlay() +{ +} + +void QtMaterialRippleOverlay::addRipple(QtMaterialRipple *ripple) +{ + ripple->setOverlay(this); + m_ripples.push_back(ripple); + ripple->start(); +} + +void QtMaterialRippleOverlay::addRipple(const QPoint &position, qreal radius) +{ + QtMaterialRipple *ripple = new QtMaterialRipple(position); + ripple->setRadiusEndValue(radius); + addRipple(ripple); +} + +void QtMaterialRippleOverlay::removeRipple(QtMaterialRipple *ripple) +{ + if (m_ripples.removeOne(ripple)) { + delete ripple; + } +} + +/*! + * \reimp + */ +void QtMaterialRippleOverlay::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(Qt::NoPen); + + if (m_useClip) { + painter.setClipPath(m_clipPath); + } + + QList::const_iterator i; + for (i = m_ripples.begin(); i != m_ripples.end(); ++i) { + paintRipple(&painter, *i); + } +} + +void QtMaterialRippleOverlay::paintRipple(QPainter *painter, QtMaterialRipple *ripple) +{ + const qreal radius = ripple->radius(); + const QPointF center = ripple->center(); + painter->setOpacity(ripple->opacity()); + painter->setBrush(ripple->brush()); + painter->drawEllipse(center, radius, radius); +} diff --git a/xxlib/qtmaterialrippleoverlay.h b/xxlib/qtmaterialrippleoverlay.h new file mode 100644 index 0000000..a813356 --- /dev/null +++ b/xxlib/qtmaterialrippleoverlay.h @@ -0,0 +1,57 @@ +#ifndef QTMATERIALRIPPLEOVERLAY_H +#define QTMATERIALRIPPLEOVERLAY_H + +#include +#include "xxlib/qtmaterialoverlaywidget.h" + +class QtMaterialRipple; + +class QtMaterialRippleOverlay : public QtMaterialOverlayWidget +{ + Q_OBJECT + +public: + explicit QtMaterialRippleOverlay(QWidget *parent = 0); + ~QtMaterialRippleOverlay(); + + void addRipple(QtMaterialRipple *ripple); + void addRipple(const QPoint &position, qreal radius = 300); + + void removeRipple(QtMaterialRipple *ripple); + + inline void setClipping(bool enable); + inline bool hasClipping() const; + + inline void setClipPath(const QPainterPath &path); + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialRippleOverlay) + + void paintRipple(QPainter *painter, QtMaterialRipple *ripple); + + QList m_ripples; + QPainterPath m_clipPath; + bool m_useClip; +}; + +inline void QtMaterialRippleOverlay::setClipping(bool enable) +{ + m_useClip = enable; + update(); +} + +inline bool QtMaterialRippleOverlay::hasClipping() const +{ + return m_useClip; +} + +inline void QtMaterialRippleOverlay::setClipPath(const QPainterPath &path) +{ + m_clipPath = path; + update(); +} + +#endif // QTMATERIALRIPPLEOVERLAY_H diff --git a/xxlib/qtmaterialstyle.cpp b/xxlib/qtmaterialstyle.cpp new file mode 100644 index 0000000..3b5081d --- /dev/null +++ b/xxlib/qtmaterialstyle.cpp @@ -0,0 +1,57 @@ +#include "xxlib/qtmaterialstyle.h" +#include +#include "xxlib/qtmaterialtheme.h" + +/*! + * \class QtMaterialStylePrivate + * \internal + */ + +QtMaterialStylePrivate::QtMaterialStylePrivate(QtMaterialStyle *q) + : q_ptr(q) +{ +} + +QtMaterialStylePrivate::~QtMaterialStylePrivate() +{ +} + +void QtMaterialStylePrivate::init() +{ + Q_Q(QtMaterialStyle); + + QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Regular.ttf"); + QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Medium.ttf"); + QFontDatabase::addApplicationFont(":/material/fonts/Roboto/Roboto-Bold.ttf"); + + q->setTheme(new QtMaterialTheme); +} + +/*! + * \class QtMaterialStyle + * \internal + */ + +void QtMaterialStyle::setTheme(QtMaterialTheme *theme) +{ + Q_D(QtMaterialStyle); + + d->theme = theme; + theme->setParent(this); +} + +QColor QtMaterialStyle::themeColor(const QString &key) const +{ + Q_D(const QtMaterialStyle); + + Q_ASSERT(d->theme); + + return d->theme->getColor(key); +} + +QtMaterialStyle::QtMaterialStyle() + : QCommonStyle(), + d_ptr(new QtMaterialStylePrivate(this)) +{ + d_func()->init(); +} diff --git a/xxlib/qtmaterialstyle.h b/xxlib/qtmaterialstyle.h new file mode 100644 index 0000000..23a7061 --- /dev/null +++ b/xxlib/qtmaterialstyle.h @@ -0,0 +1,37 @@ +#ifndef QTMATERIALSTYLE_H +#define QTMATERIALSTYLE_H + +#include +#include "xxlib/qtmaterialstyle_p.h" + +class QtMaterialTheme; + +class QtMaterialStyle : public QCommonStyle +{ + Q_OBJECT + +public: + inline static QtMaterialStyle &instance(); + + void setTheme(QtMaterialTheme *theme); + QColor themeColor(const QString &key) const; + +protected: + const QScopedPointer d_ptr; + +private: + Q_DECLARE_PRIVATE(QtMaterialStyle) + + QtMaterialStyle(); + + QtMaterialStyle(QtMaterialStyle const &); + void operator=(QtMaterialStyle const &); +}; + +inline QtMaterialStyle &QtMaterialStyle::instance() +{ + static QtMaterialStyle instance; + return instance; +} + +#endif // QTMATERIALSTYLE_H diff --git a/xxlib/qtmaterialstyle_p.h b/xxlib/qtmaterialstyle_p.h new file mode 100644 index 0000000..d59ca41 --- /dev/null +++ b/xxlib/qtmaterialstyle_p.h @@ -0,0 +1,24 @@ +#ifndef QTMATERIALSTYLE_P_H +#define QTMATERIALSTYLE_P_H + +#include + +class QtMaterialStyle; +class QtMaterialTheme; + +class QtMaterialStylePrivate +{ + Q_DISABLE_COPY(QtMaterialStylePrivate) + Q_DECLARE_PUBLIC(QtMaterialStyle) + +public: + QtMaterialStylePrivate(QtMaterialStyle *q); + ~QtMaterialStylePrivate(); + + void init(); + + QtMaterialStyle *const q_ptr; + QtMaterialTheme *theme; +}; + +#endif // QTMATERIALSTYLE_P_H diff --git a/xxlib/qtmaterialtheme.cpp b/xxlib/qtmaterialtheme.cpp new file mode 100644 index 0000000..9316930 --- /dev/null +++ b/xxlib/qtmaterialtheme.cpp @@ -0,0 +1,152 @@ +#include "xxlib/qtmaterialtheme.h" +#include "xxlib/qtmaterialtheme_p.h" +#include + +/*! + * \class QtMaterialThemePrivate + * \internal + */ + +QtMaterialThemePrivate::QtMaterialThemePrivate(QtMaterialTheme *q) + : q_ptr(q) +{ +} + +QtMaterialThemePrivate::~QtMaterialThemePrivate() +{ +} + +QColor QtMaterialThemePrivate::rgba(int r, int g, int b, qreal a) const +{ + QColor color(r, g, b); + color.setAlphaF(a); + return color; +} + +/*! + * \class QtMaterialTheme + */ + +QtMaterialTheme::QtMaterialTheme(QObject *parent) + : QObject(parent), + d_ptr(new QtMaterialThemePrivate(this)) +{ + setColor("primary1", XXMaterial::cyan500); + setColor("primary2", XXMaterial::cyan700); + setColor("primary3", XXMaterial::lightBlack); + setColor("accent1", XXMaterial::pinkA200); + setColor("accent2", XXMaterial::grey100); + setColor("accent3", XXMaterial::grey500); + setColor("text", XXMaterial::darkBlack); + setColor("alternateText", XXMaterial::white); + setColor("canvas", XXMaterial::white); + setColor("border", XXMaterial::grey300); + setColor("disabled", XXMaterial::minBlack); + setColor("disabled2", XXMaterial::faintBlack); + setColor("disabled3", XXMaterial::grey300); +} + +QtMaterialTheme::~QtMaterialTheme() +{ +} + +QColor QtMaterialTheme::getColor(const QString &key) const +{ + Q_D(const QtMaterialTheme); + + if (!d->colors.contains(key)) { + qWarning() << "A theme color matching the key '" << key << "' could not be found."; + return QColor(); + } + return d->colors.value(key); +} + +void QtMaterialTheme::setColor(const QString &key, const QColor &color) +{ + Q_D(QtMaterialTheme); + + d->colors.insert(key, color); +} + +void QtMaterialTheme::setColor(const QString &key, XXMaterial::Color color) +{ + Q_D(QtMaterialTheme); + + static const QColor palette[] = { + QColor("#ffebee"), QColor("#ffcdd2"), QColor("#ef9a9a"), QColor("#e57373"), + QColor("#ef5350"), QColor("#f44336"), QColor("#e53935"), QColor("#d32f2f"), + QColor("#c62828"), QColor("#b71c1c"), QColor("#ff8a80"), QColor("#ff5252"), + QColor("#ff1744"), QColor("#d50000"), QColor("#fce4ec"), QColor("#f8bbd0"), + QColor("#f48fb1"), QColor("#f06292"), QColor("#ec407a"), QColor("#e91e63"), + QColor("#d81b60"), QColor("#c2185b"), QColor("#ad1457"), QColor("#880e4f"), + QColor("#ff80ab"), QColor("#ff4081"), QColor("#f50057"), QColor("#c51162"), + QColor("#f3e5f5"), QColor("#e1bee7"), QColor("#ce93d8"), QColor("#ba68c8"), + QColor("#ab47bc"), QColor("#9c27b0"), QColor("#8e24aa"), QColor("#7b1fa2"), + QColor("#6a1b9a"), QColor("#4a148c"), QColor("#ea80fc"), QColor("#e040fb"), + QColor("#d500f9"), QColor("#aa00ff"), QColor("#ede7f6"), QColor("#d1c4e9"), + QColor("#b39ddb"), QColor("#9575cd"), QColor("#7e57c2"), QColor("#673ab7"), + QColor("#5e35b1"), QColor("#512da8"), QColor("#4527a0"), QColor("#311b92"), + QColor("#b388ff"), QColor("#7c4dff"), QColor("#651fff"), QColor("#6200ea"), + QColor("#e8eaf6"), QColor("#c5cae9"), QColor("#9fa8da"), QColor("#7986cb"), + QColor("#5c6bc0"), QColor("#3f51b5"), QColor("#3949ab"), QColor("#303f9f"), + QColor("#283593"), QColor("#1a237e"), QColor("#8c9eff"), QColor("#536dfe"), + QColor("#3d5afe"), QColor("#304ffe"), QColor("#e3f2fd"), QColor("#bbdefb"), + QColor("#90caf9"), QColor("#64b5f6"), QColor("#42a5f5"), QColor("#2196f3"), + QColor("#1e88e5"), QColor("#1976d2"), QColor("#1565c0"), QColor("#0d47a1"), + QColor("#82b1ff"), QColor("#448aff"), QColor("#2979ff"), QColor("#2962ff"), + QColor("#e1f5fe"), QColor("#b3e5fc"), QColor("#81d4fa"), QColor("#4fc3f7"), + QColor("#29b6f6"), QColor("#03a9f4"), QColor("#039be5"), QColor("#0288d1"), + QColor("#0277bd"), QColor("#01579b"), QColor("#80d8ff"), QColor("#40c4ff"), + QColor("#00b0ff"), QColor("#0091ea"), QColor("#e0f7fa"), QColor("#b2ebf2"), + QColor("#80deea"), QColor("#4dd0e1"), QColor("#26c6da"), QColor("#00bcd4"), + QColor("#00acc1"), QColor("#0097a7"), QColor("#00838f"), QColor("#006064"), + QColor("#84ffff"), QColor("#18ffff"), QColor("#00e5ff"), QColor("#00b8d4"), + QColor("#e0f2f1"), QColor("#b2dfdb"), QColor("#80cbc4"), QColor("#4db6ac"), + QColor("#26a69a"), QColor("#009688"), QColor("#00897b"), QColor("#00796b"), + QColor("#00695c"), QColor("#004d40"), QColor("#a7ffeb"), QColor("#64ffda"), + QColor("#1de9b6"), QColor("#00bfa5"), QColor("#e8f5e9"), QColor("#c8e6c9"), + QColor("#a5d6a7"), QColor("#81c784"), QColor("#66bb6a"), QColor("#4caf50"), + QColor("#43a047"), QColor("#388e3c"), QColor("#2e7d32"), QColor("#1b5e20"), + QColor("#b9f6ca"), QColor("#69f0ae"), QColor("#00e676"), QColor("#00c853"), + QColor("#f1f8e9"), QColor("#dcedc8"), QColor("#c5e1a5"), QColor("#aed581"), + QColor("#9ccc65"), QColor("#8bc34a"), QColor("#7cb342"), QColor("#689f38"), + QColor("#558b2f"), QColor("#33691e"), QColor("#ccff90"), QColor("#b2ff59"), + QColor("#76ff03"), QColor("#64dd17"), QColor("#f9fbe7"), QColor("#f0f4c3"), + QColor("#e6ee9c"), QColor("#dce775"), QColor("#d4e157"), QColor("#cddc39"), + QColor("#c0ca33"), QColor("#afb42b"), QColor("#9e9d24"), QColor("#827717"), + QColor("#f4ff81"), QColor("#eeff41"), QColor("#c6ff00"), QColor("#aeea00"), + QColor("#fffde7"), QColor("#fff9c4"), QColor("#fff59d"), QColor("#fff176"), + QColor("#ffee58"), QColor("#ffeb3b"), QColor("#fdd835"), QColor("#fbc02d"), + QColor("#f9a825"), QColor("#f57f17"), QColor("#ffff8d"), QColor("#ffff00"), + QColor("#ffea00"), QColor("#ffd600"), QColor("#fff8e1"), QColor("#ffecb3"), + QColor("#ffe082"), QColor("#ffd54f"), QColor("#ffca28"), QColor("#ffc107"), + QColor("#ffb300"), QColor("#ffa000"), QColor("#ff8f00"), QColor("#ff6f00"), + QColor("#ffe57f"), QColor("#ffd740"), QColor("#ffc400"), QColor("#ffab00"), + QColor("#fff3e0"), QColor("#ffe0b2"), QColor("#ffcc80"), QColor("#ffb74d"), + QColor("#ffa726"), QColor("#ff9800"), QColor("#fb8c00"), QColor("#f57c00"), + QColor("#ef6c00"), QColor("#e65100"), QColor("#ffd180"), QColor("#ffab40"), + QColor("#ff9100"), QColor("#ff6d00"), QColor("#fbe9e7"), QColor("#ffccbc"), + QColor("#ffab91"), QColor("#ff8a65"), QColor("#ff7043"), QColor("#ff5722"), + QColor("#f4511e"), QColor("#e64a19"), QColor("#d84315"), QColor("#bf360c"), + QColor("#ff9e80"), QColor("#ff6e40"), QColor("#ff3d00"), QColor("#dd2c00"), + QColor("#efebe9"), QColor("#d7ccc8"), QColor("#bcaaa4"), QColor("#a1887f"), + QColor("#8d6e63"), QColor("#795548"), QColor("#6d4c41"), QColor("#5d4037"), + QColor("#4e342e"), QColor("#3e2723"), QColor("#eceff1"), QColor("#cfd8dc"), + QColor("#b0bec5"), QColor("#90a4ae"), QColor("#78909c"), QColor("#607d8b"), + QColor("#546e7a"), QColor("#455a64"), QColor("#37474f"), QColor("#263238"), + QColor("#fafafa"), QColor("#f5f5f5"), QColor("#eeeeee"), QColor("#e0e0e0"), + QColor("#bdbdbd"), QColor("#9e9e9e"), QColor("#757575"), QColor("#616161"), + QColor("#424242"), QColor("#212121"), QColor("#000000"), QColor("#ffffff"), + d->rgba(0, 0, 0, 0), + d->rgba(0, 0, 0, 1), + d->rgba(0, 0, 0, 0.87), + d->rgba(0, 0, 0, 0.54), + d->rgba(0, 0, 0, 0.26), + d->rgba(0, 0, 0, 0.12), + d->rgba(255, 255, 255, 1), + d->rgba(255, 255, 255, 0.87), + d->rgba(255, 255, 255, 0.54) + }; + + d->colors.insert(key, palette[color]); +} diff --git a/xxlib/qtmaterialtheme.h b/xxlib/qtmaterialtheme.h new file mode 100644 index 0000000..562e919 --- /dev/null +++ b/xxlib/qtmaterialtheme.h @@ -0,0 +1,341 @@ +#ifndef QTMATERIALTHEME_H +#define QTMATERIALTHEME_H + +#include +#include +#include + +namespace XXMaterial +{ + enum ButtonPreset { + FlatPreset, + CheckablePreset + }; + + enum RippleStyle { + CenteredRipple, + PositionedRipple, + NoRipple + }; + + enum OverlayStyle { + NoOverlay, + TintedOverlay, + GrayOverlay + }; + + enum Role { + Default, + Primary, + Secondary + }; + + enum ButtonIconPlacement { + LeftIcon, + RightIcon + }; + + enum ProgressType { + DeterminateProgress, + IndeterminateProgress + }; + + enum AvatarType { + ImageAvatar, + IconAvatar, + LetterAvatar + }; + + enum Color { + red50, + red100, + red200, + red300, + red400, + red500, + red600, + red700, + red800, + red900, + redA100, + redA200, + redA400, + redA700, + pink50, + pink100, + pink200, + pink300, + pink400, + pink500, + pink600, + pink700, + pink800, + pink900, + pinkA100, + pinkA200, + pinkA400, + pinkA700, + purple50, + purple100, + purple200, + purple300, + purple400, + purple500, + purple600, + purple700, + purple800, + purple900, + purpleA100, + purpleA200, + purpleA400, + purpleA700, + deepPurple50, + deepPurple100, + deepPurple200, + deepPurple300, + deepPurple400, + deepPurple500, + deepPurple600, + deepPurple700, + deepPurple800, + deepPurple900, + deepPurpleA100, + deepPurpleA200, + deepPurpleA400, + deepPurpleA700, + indigo50, + indigo100, + indigo200, + indigo300, + indigo400, + indigo500, + indigo600, + indigo700, + indigo800, + indigo900, + indigoA100, + indigoA200, + indigoA400, + indigoA700, + blue50, + blue100, + blue200, + blue300, + blue400, + blue500, + blue600, + blue700, + blue800, + blue900, + blueA100, + blueA200, + blueA400, + blueA700, + lightBlue50, + lightBlue100, + lightBlue200, + lightBlue300, + lightBlue400, + lightBlue500, + lightBlue600, + lightBlue700, + lightBlue800, + lightBlue900, + lightBlueA100, + lightBlueA200, + lightBlueA400, + lightBlueA700, + cyan50, + cyan100, + cyan200, + cyan300, + cyan400, + cyan500, + cyan600, + cyan700, + cyan800, + cyan900, + cyanA100, + cyanA200, + cyanA400, + cyanA700, + teal50, + teal100, + teal200, + teal300, + teal400, + teal500, + teal600, + teal700, + teal800, + teal900, + tealA100, + tealA200, + tealA400, + tealA700, + green50, + green100, + green200, + green300, + green400, + green500, + green600, + green700, + green800, + green900, + greenA100, + greenA200, + greenA400, + greenA700, + lightGreen50, + lightGreen100, + lightGreen200, + lightGreen300, + lightGreen400, + lightGreen500, + lightGreen600, + lightGreen700, + lightGreen800, + lightGreen900, + lightGreenA100, + lightGreenA200, + lightGreenA400, + lightGreenA700, + lime50, + lime100, + lime200, + lime300, + lime400, + lime500, + lime600, + lime700, + lime800, + lime900, + limeA100, + limeA200, + limeA400, + limeA700, + yellow50, + yellow100, + yellow200, + yellow300, + yellow400, + yellow500, + yellow600, + yellow700, + yellow800, + yellow900, + yellowA100, + yellowA200, + yellowA400, + yellowA700, + amber50, + amber100, + amber200, + amber300, + amber400, + amber500, + amber600, + amber700, + amber800, + amber900, + amberA100, + amberA200, + amberA400, + amberA700, + orange50, + orange100, + orange200, + orange300, + orange400, + orange500, + orange600, + orange700, + orange800, + orange900, + orangeA100, + orangeA200, + orangeA400, + orangeA700, + deepOrange50, + deepOrange100, + deepOrange200, + deepOrange300, + deepOrange400, + deepOrange500, + deepOrange600, + deepOrange700, + deepOrange800, + deepOrange900, + deepOrangeA100, + deepOrangeA200, + deepOrangeA400, + deepOrangeA700, + brown50, + brown100, + brown200, + brown300, + brown400, + brown500, + brown600, + brown700, + brown800, + brown900, + blueGrey50, + blueGrey100, + blueGrey200, + blueGrey300, + blueGrey400, + blueGrey500, + blueGrey600, + blueGrey700, + blueGrey800, + blueGrey900, + grey50, + grey100, + grey200, + grey300, + grey400, + grey500, + grey600, + grey700, + grey800, + grey900, + black, + white, + transparent, + fullBlack, + darkBlack, + lightBlack, + minBlack, + faintBlack, + fullWhite, + darkWhite, + lightWhite + }; +} + +class QtMaterialThemePrivate; + +class QtMaterialTheme : public QObject +{ + Q_OBJECT + +public: + explicit QtMaterialTheme(QObject *parent = 0); + ~QtMaterialTheme(); + + QColor getColor(const QString &key) const; + + void setColor(const QString &key, const QColor &color); + void setColor(const QString &key, XXMaterial::Color color); + +protected: + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialTheme) + Q_DECLARE_PRIVATE(QtMaterialTheme) +}; + +#endif // QTMATERIALTHEME_H diff --git a/xxlib/qtmaterialtheme_p.h b/xxlib/qtmaterialtheme_p.h new file mode 100644 index 0000000..d0ef178 --- /dev/null +++ b/xxlib/qtmaterialtheme_p.h @@ -0,0 +1,24 @@ +#ifndef QTMATERIALTHEME_P_H +#define QTMATERIALTHEME_P_H + +#include +#include + +class QtMaterialTheme; + +class QtMaterialThemePrivate +{ + Q_DISABLE_COPY(QtMaterialThemePrivate) + Q_DECLARE_PUBLIC(QtMaterialTheme) + +public: + QtMaterialThemePrivate(QtMaterialTheme *q); + ~QtMaterialThemePrivate(); + + QColor rgba(int r, int g, int b, qreal a) const; + + QtMaterialTheme *const q_ptr; + QHash colors; +}; + +#endif // QTMATERIALTHEME_P_H diff --git a/yy/flatbuttonsettingseditor.cpp b/yy/flatbuttonsettingseditor.cpp new file mode 100644 index 0000000..bb3004f --- /dev/null +++ b/yy/flatbuttonsettingseditor.cpp @@ -0,0 +1,576 @@ +#include "yy/flatbuttonsettingseditor.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xx/qtmaterialflatbutton.h" + +FlatButtonSettingsEditor::FlatButtonSettingsEditor(QWidget *parent) + : QWidget(parent), + m_flatbutton(new QtMaterialFlatButton("I am flat")) +{ + QCheckBox *checkbox; + QComboBox *combo; + QLabel *label; + QLineEdit *edit; + QSlider *slider; + QVBoxLayout *vlayout; + QHBoxLayout *groupboxlayout; + QGridLayout *grid; + QGroupBox *groupbox; + + vlayout = new QVBoxLayout; + setLayout(vlayout); + + groupbox = new QGroupBox; + groupbox->setTitle("Properties"); + groupboxlayout = new QHBoxLayout; + groupbox->setLayout(groupboxlayout); + + QVBoxLayout *vlayout2 = new QVBoxLayout; + + groupboxlayout->addLayout(vlayout2); + groupboxlayout->addSpacing(40); + + vlayout->addStretch(1); + vlayout->addWidget(m_flatbutton); + m_flatbutton->setFixedWidth(400); + vlayout->setAlignment(m_flatbutton, Qt::AlignCenter); + + connect(m_flatbutton, SIGNAL(toggled(bool)), this, SLOT(buttonToggled())); + + vlayout->addSpacing(40); + + vlayout->addWidget(groupbox); + + // + + checkbox = new QCheckBox; + checkbox->setText("Disabled"); + vlayout2->addWidget(checkbox); + + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(settingDisabledToggled(bool))); + + // + + checkbox = new QCheckBox; + checkbox->setText("Checkable"); + vlayout2->addWidget(checkbox); + + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(settingCheckableToggled(bool))); + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(buttonToggled())); + + // + + m_checkedCheckbox = new QCheckBox; + m_checkedCheckbox->setText("Checked"); + m_checkedCheckbox->setDisabled(true); + vlayout2->addWidget(m_checkedCheckbox); + + connect(m_checkedCheckbox, SIGNAL(clicked(bool)), this, SLOT(setButtonChecked(bool))); + + // + + checkbox = new QCheckBox; + checkbox->setText("Show halo"); + checkbox->setChecked(true); + vlayout2->addWidget(checkbox); + + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(settingShowHaloToggled(bool))); + + // + + checkbox = new QCheckBox; + checkbox->setText("Transparent background"); + checkbox->setChecked(true); + vlayout2->addWidget(checkbox); + + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(settingTransparentBgToggled(bool))); + + // + + checkbox = new QCheckBox; + checkbox->setText("Icon"); + vlayout2->addWidget(checkbox); + + connect(checkbox, SIGNAL(clicked(bool)), this, SLOT(settingIconToggled(bool))); + + // + + vlayout2->addStretch(); + + // + + grid = new QGridLayout; + + label = new QLabel("Button role"); + + combo = new QComboBox; + combo->addItem("Default"); + combo->addItem("Primary"); + combo->addItem("Secondary"); + + grid->addWidget(label, 0, 0); + grid->addWidget(combo, 0, 2); + + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(settingRoleChanged(int))); + + // + + label = new QLabel("Ripple style"); + + combo = new QComboBox; + combo->addItem("Positioned"); + combo->addItem("Centered"); + + grid->addWidget(label, 1, 0); + grid->addWidget(combo, 1, 2); + + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(settingRipplePositionChanged(int))); + + // + + label = new QLabel("Hover style"); + + m_overlayStyleCombo = new QComboBox; + m_overlayStyleCombo->addItem("No overlay"); + m_overlayStyleCombo->addItem("Tinted"); + m_overlayStyleCombo->addItem("Gray"); + m_overlayStyleCombo->setCurrentIndex(0); + + grid->addWidget(label, 2, 0); + grid->addWidget(m_overlayStyleCombo, 2, 2); + + connect(m_overlayStyleCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(settingOverlayStyleChanged(int))); + + // + + label = new QLabel("Icon placement"); + + combo = new QComboBox; + combo->addItem("Left"); + combo->addItem("Right"); + + grid->addWidget(label, 3, 0); + grid->addWidget(combo, 3, 2); + + connect(combo, SIGNAL(currentIndexChanged(int)), this, SLOT(settingIconPlacementChanged(int))); + + // + + label = new QLabel("Corner radius"); + m_cornerRadiusEdit = new QLineEdit; + m_cornerRadiusEdit->setReadOnly(true); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(0, 220); + slider->setSliderPosition(m_flatbutton->cornerRadius()); + m_cornerRadiusEdit->setText("3"); + + grid->setColumnStretch(2, 3); + + grid->addWidget(label, 4, 0); + grid->addWidget(m_cornerRadiusEdit, 4, 1); + grid->addWidget(slider, 4, 2); + + connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(settingCornerRadiusChanged(int))); + + // + + label = new QLabel("Overlay opacity"); + m_baseOpacityEdit = new QLineEdit; + m_baseOpacityEdit->setReadOnly(true); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(0, 100); + slider->setSliderPosition(m_flatbutton->baseOpacity()*100); + + QString s; + s.setNum(m_flatbutton->baseOpacity()); + m_baseOpacityEdit->setText(s); + + grid->addWidget(label, 5, 0); + grid->addWidget(m_baseOpacityEdit, 5, 1); + grid->addWidget(slider, 5, 2); + + connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(settingBaseOpacityChanged(int))); + + // + + label = new QLabel("Icon size"); + m_iconSizeEdit = new QLineEdit; + m_iconSizeEdit->setReadOnly(true); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(4, 148); + slider->setSliderPosition(m_flatbutton->iconSize().width()); + m_iconSizeEdit->setText(QString::number(slider->value())); + + grid->addWidget(label, 6, 0); + grid->addWidget(m_iconSizeEdit, 6, 1); + grid->addWidget(slider, 6, 2); + + connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(settingIconSizeChanged(int))); + + // + + label = new QLabel("Font size"); + m_fontSizeEdit = new QLineEdit; + m_fontSizeEdit->setReadOnly(true); + + slider = new QSlider(Qt::Horizontal); + slider->setRange(10, 80); + slider->setSliderPosition(m_flatbutton->fontSize()*2); + + s.setNum(m_flatbutton->fontSize()); + m_fontSizeEdit->setText(s); + + grid->addWidget(label, 7, 0); + grid->addWidget(m_fontSizeEdit, 7, 1); + grid->addWidget(slider, 7, 2); + + connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(settingFontSizeChanged(int))); + + // + + label = new QLabel("Button text"); + + edit = new QLineEdit("I am flat"); + + grid->addWidget(label, 8, 0); + grid->addWidget(edit, 8, 1, 1, 2); + + connect(edit, SIGNAL(textChanged(QString)), this, SLOT(settingButtonTextChanged(QString))); + + // + + groupboxlayout->addLayout(grid); + grid = new QGridLayout; + + groupbox = new QGroupBox; + groupbox->setTitle("Colors"); + groupbox->setLayout(grid); + + vlayout->addWidget(groupbox); + + // + + QCheckBox *themeColorsCheckbox; + + themeColorsCheckbox = new QCheckBox; + themeColorsCheckbox->setText("Use theme colors"); + themeColorsCheckbox->setChecked(true); + grid->addWidget(themeColorsCheckbox, 9, 0, 1, 2); + + connect(themeColorsCheckbox, SIGNAL(clicked(bool)), this, SLOT(settingThemeColorsToggled(bool))); + + // + + label = new QLabel("Background color"); + m_backgroundColorValue = new QPushButton("Click to select"); + m_backgroundColorValue->setFlat(true); + + label->setDisabled(true); + m_backgroundColorValue->setDisabled(true); + + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), label, SLOT(setDisabled(bool))); + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), m_backgroundColorValue, SLOT(setDisabled(bool))); + + connect(m_backgroundColorValue, SIGNAL(clicked(bool)), this, SLOT(selectBackgroundColor())); + + grid->addWidget(label, 10, 0); + grid->addWidget(m_backgroundColorValue, 10, 1); + + // + + label = new QLabel("Foreground color"); + m_foregroundColorValue = new QPushButton("Click to select"); + m_foregroundColorValue->setFlat(true); + + label->setDisabled(true); + m_foregroundColorValue->setDisabled(true); + + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), label, SLOT(setDisabled(bool))); + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), m_foregroundColorValue, SLOT(setDisabled(bool))); + + connect(m_foregroundColorValue, SIGNAL(clicked(bool)), this, SLOT(selectForegroundColor())); + + grid->addWidget(label, 11, 0); + grid->addWidget(m_foregroundColorValue, 11, 1); + + // + + label = new QLabel("Overlay color"); + m_overlayColorValue = new QPushButton("Click to select"); + m_overlayColorValue->setFlat(true); + + label->setDisabled(true); + m_overlayColorValue->setDisabled(true); + + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), label, SLOT(setDisabled(bool))); + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), m_overlayColorValue, SLOT(setDisabled(bool))); + + connect(m_overlayColorValue, SIGNAL(clicked(bool)), this, SLOT(selectOverlayColor())); + + grid->addWidget(label, 12, 0); + grid->addWidget(m_overlayColorValue, 12, 1); + + // + + label = new QLabel("Disabled background color"); + m_disabledBackgroundColorValue = new QPushButton("Click to select"); + m_disabledBackgroundColorValue->setFlat(true); + + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), label, SLOT(setDisabled(bool))); + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), m_disabledBackgroundColorValue, SLOT(setDisabled(bool))); + + label->setDisabled(true); + m_disabledBackgroundColorValue->setDisabled(true); + + connect(m_disabledBackgroundColorValue, SIGNAL(clicked(bool)), this, SLOT(selectDisabledBackgroundColor())); + + grid->addWidget(label, 13, 0); + grid->addWidget(m_disabledBackgroundColorValue, 13, 1); + + // + + label = new QLabel("Disabled foreground color"); + m_disabledForegroundColorValue = new QPushButton("Click to select"); + m_disabledForegroundColorValue->setFlat(true); + + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), label, SLOT(setDisabled(bool))); + connect(themeColorsCheckbox, SIGNAL(toggled(bool)), m_disabledForegroundColorValue, SLOT(setDisabled(bool))); + + connect(m_disabledForegroundColorValue, SIGNAL(clicked(bool)), this, SLOT(selectDisabledForegroundColor())); + + label->setDisabled(true); + m_disabledForegroundColorValue->setDisabled(true); + + grid->addWidget(label, 14, 0); + grid->addWidget(m_disabledForegroundColorValue, 14, 1); + + // + + vlayout->addStretch(1); +} + +FlatButtonSettingsEditor::~FlatButtonSettingsEditor() +{ +} + +void FlatButtonSettingsEditor::paintEvent(QPaintEvent *event) +{ + QPainter painter(this); + + QRect r(m_flatbutton->geometry()); + + painter.fillRect(r.adjusted(-160, -60, 160, 60), Qt::white); + + QWidget::paintEvent(event); +} + +void FlatButtonSettingsEditor::settingDisabledToggled(bool value) +{ + m_flatbutton->setDisabled(value); +} + +void FlatButtonSettingsEditor::settingCheckableToggled(bool value) +{ + m_flatbutton->setCheckable(value); + m_checkedCheckbox->setEnabled(value); + m_checkedCheckbox->setChecked(false); +} + +void FlatButtonSettingsEditor::setButtonChecked(bool value) +{ + m_flatbutton->setChecked(value); +} + +void FlatButtonSettingsEditor::settingShowHaloToggled(bool value) +{ + m_flatbutton->setHaloVisible(value); +} + +void FlatButtonSettingsEditor::settingTransparentBgToggled(bool value) +{ + m_flatbutton->setBackgroundMode(value ? Qt::TransparentMode : Qt::OpaqueMode); +} + +void FlatButtonSettingsEditor::settingThemeColorsToggled(bool value) +{ + m_flatbutton->setUseThemeColors(value); +} + +void FlatButtonSettingsEditor::settingIconToggled(bool value) +{ + if (value) { + m_flatbutton->setIcon(QIcon("../qt-material-widgets/ic_star_black_24px.svg")); + } else { + m_flatbutton->setIcon(QIcon()); + } +} + +void FlatButtonSettingsEditor::settingRoleChanged(int index) +{ + switch (index) + { + case 0: + m_flatbutton->setRole(XXMaterial::Default); + break; + case 1: + m_flatbutton->setRole(XXMaterial::Primary); + break; + case 2: + m_flatbutton->setRole(XXMaterial::Secondary); + break; + default: + break; + } +} + +void FlatButtonSettingsEditor::settingRipplePositionChanged(int index) +{ + switch (index) + { + case 0: + m_flatbutton->setRippleStyle(XXMaterial::PositionedRipple); + break; + case 1: + m_flatbutton->setRippleStyle(XXMaterial::CenteredRipple); + break; + default: + break; + } +} + +void FlatButtonSettingsEditor::settingOverlayStyleChanged(int index) +{ + switch (index) + { + case 0: + m_flatbutton->setOverlayStyle(XXMaterial::NoOverlay); + break; + case 1: + m_flatbutton->setOverlayStyle(XXMaterial::TintedOverlay); + break; + case 2: + m_flatbutton->setOverlayStyle(XXMaterial::GrayOverlay); + break; + default: + break; + } +} + +void FlatButtonSettingsEditor::settingIconPlacementChanged(int index) +{ + switch (index) + { + case 0: + m_flatbutton->setIconPlacement(XXMaterial::LeftIcon); + break; + case 1: + m_flatbutton->setIconPlacement(XXMaterial::RightIcon); + break; + default: + break; + } +} + +void FlatButtonSettingsEditor::settingCornerRadiusChanged(int value) +{ + m_flatbutton->setCornerRadius(value); + m_cornerRadiusEdit->setText(QString::number(value)); +} + +void FlatButtonSettingsEditor::settingBaseOpacityChanged(int value) +{ + const qreal r = static_cast(value)/100; + m_flatbutton->setBaseOpacity(r); + + QString s; + s.setNum(r); + m_baseOpacityEdit->setText(s); +} + +void FlatButtonSettingsEditor::settingIconSizeChanged(int value) +{ + m_flatbutton->setIconSize(QSize(value, value)); + m_iconSizeEdit->setText(QString::number(value)); +} + +void FlatButtonSettingsEditor::settingFontSizeChanged(int value) +{ + const qreal r = static_cast(value)/2; + m_flatbutton->setFontSize(r); + + QString s; + s.setNum(r); + m_fontSizeEdit->setText(s); +} + +void FlatButtonSettingsEditor::settingButtonTextChanged(QString text) +{ + m_flatbutton->setText(text); +} + +void FlatButtonSettingsEditor::buttonToggled() +{ + m_checkedCheckbox->setChecked(m_flatbutton->isChecked()); +} + +void FlatButtonSettingsEditor::selectBackgroundColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + m_flatbutton->setBackgroundColor(color); + m_backgroundColorValue->setText(color.name(QColor::HexRgb)); + } +} + +void FlatButtonSettingsEditor::selectForegroundColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + m_flatbutton->setForegroundColor(color); + m_foregroundColorValue->setText(color.name(QColor::HexRgb)); + } +} + +void FlatButtonSettingsEditor::selectOverlayColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + m_flatbutton->setOverlayColor(color); + m_overlayColorValue->setText(color.name(QColor::HexRgb)); + m_overlayStyleCombo->setCurrentIndex(1); + } +} + +void FlatButtonSettingsEditor::selectDisabledBackgroundColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + m_flatbutton->setDisabledBackgroundColor(color); + m_disabledBackgroundColorValue->setText(color.name(QColor::HexRgb)); + } +} + +void FlatButtonSettingsEditor::selectDisabledForegroundColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + m_flatbutton->setDisabledForegroundColor(color); + m_disabledForegroundColorValue->setText(color.name(QColor::HexRgb)); + } +} diff --git a/yy/flatbuttonsettingseditor.h b/yy/flatbuttonsettingseditor.h new file mode 100644 index 0000000..62c5c6f --- /dev/null +++ b/yy/flatbuttonsettingseditor.h @@ -0,0 +1,63 @@ +#ifndef FLATBUTTONSETTINGSMANAGER_H +#define FLATBUTTONSETTINGSMANAGER_H + +#include + +class QLabel; +class QPushButton; +class QCheckBox; +class QtMaterialFlatButton; +class QComboBox; +class QLineEdit; + +class FlatButtonSettingsEditor : public QWidget +{ + Q_OBJECT + +public: + explicit FlatButtonSettingsEditor(QWidget *parent = 0); + ~FlatButtonSettingsEditor(); + +protected: + void paintEvent(QPaintEvent *event); + +protected slots: + void settingDisabledToggled(bool value); + void settingCheckableToggled(bool value); + void setButtonChecked(bool value); + void settingShowHaloToggled(bool value); + void settingTransparentBgToggled(bool value); + void settingThemeColorsToggled(bool value); + void settingIconToggled(bool value); + void settingRoleChanged(int index); + void settingRipplePositionChanged(int index); + void settingOverlayStyleChanged(int index); + void settingIconPlacementChanged(int index); + void settingCornerRadiusChanged(int value); + void settingBaseOpacityChanged(int value); + void settingIconSizeChanged(int value); + void settingFontSizeChanged(int value); + void settingButtonTextChanged(QString text); + void buttonToggled(); + void selectBackgroundColor(); + void selectForegroundColor(); + void selectOverlayColor(); + void selectDisabledBackgroundColor(); + void selectDisabledForegroundColor(); + +private: + QtMaterialFlatButton *m_flatbutton; + QPushButton *m_backgroundColorValue; + QPushButton *m_foregroundColorValue; + QPushButton *m_overlayColorValue; + QPushButton *m_disabledBackgroundColorValue; + QPushButton *m_disabledForegroundColorValue; + QComboBox *m_overlayStyleCombo; + QLineEdit *m_cornerRadiusEdit; + QLineEdit *m_baseOpacityEdit; + QLineEdit *m_iconSizeEdit; + QLineEdit *m_fontSizeEdit; + QCheckBox *m_checkedCheckbox; +}; + +#endif // FLATBUTTONSETTINGSMANAGER_H