diff --git a/components/components.pro b/components/components.pro index 72914f3..8582164 100644 --- a/components/components.pro +++ b/components/components.pro @@ -29,7 +29,12 @@ SOURCES = \ qtmaterialtextfield_internal.cpp \ qtmaterialtextfield.cpp \ qtmaterialtabs_internal.cpp \ - qtmaterialtabs.cpp + qtmaterialtabs.cpp \ + qtmaterialselectfield.cpp \ + qtmaterialmenuitem_internal.cpp \ + qtmaterialmenuitem.cpp \ + qtmaterialcollapsiblemenu_internal.cpp \ + qtmaterialcollapsiblemenu.cpp HEADERS = \ qtmaterialavatar_p.h \ qtmaterialavatar.h \ @@ -77,6 +82,14 @@ HEADERS = \ qtmaterialtextfield.h \ qtmaterialtabs_internal.h \ qtmaterialtabs_p.h \ - qtmaterialtabs.h + qtmaterialtabs.h \ + qtmaterialselectfield_p.h \ + qtmaterialselectfield.h \ + qtmaterialmenuitem_internal.h \ + qtmaterialmenuitem_p.h \ + qtmaterialmenuitem.h \ + qtmaterialcollapsiblemenu_internal.h \ + qtmaterialcollapsiblemenu_p.h \ + qtmaterialcollapsiblemenu.h RESOURCES += \ resources.qrc diff --git a/components/qtmaterialcollapsiblemenu.cpp b/components/qtmaterialcollapsiblemenu.cpp new file mode 100644 index 0000000..269e8c4 --- /dev/null +++ b/components/qtmaterialcollapsiblemenu.cpp @@ -0,0 +1,236 @@ +#include "xx/qtmaterialcollapsiblemenu.h" +#include "xx/qtmaterialcollapsiblemenu_p.h" +#include +#include +#include +#include "xx/qtmaterialcollapsiblemenu_internal.h" +#include "xx/qtmaterialmenuitem.h" +#include "xx/qtmaterialscrollbar.h" +#include "xxlib/qtmaterialstyle.h" +#include "xxlib/qtmaterialstatetransitionevent.h" + +/*! + * \class QtMaterialCollapsibleMenuPrivate + * \internal + */ + +QtMaterialCollapsibleMenuPrivate::QtMaterialCollapsibleMenuPrivate(QtMaterialCollapsibleMenu *q) + : q_ptr(q) +{ +} + +QtMaterialCollapsibleMenuPrivate::~QtMaterialCollapsibleMenuPrivate() +{ +} + +void QtMaterialCollapsibleMenuPrivate::init() +{ + Q_Q(QtMaterialCollapsibleMenu); + + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + QtMaterialScrollBar *scrollBar = new QtMaterialScrollBar; + + scrollArea = new QScrollArea; + mainWidget = new QWidget; + menuLayout = new QVBoxLayout; + proxy = new QtMaterialCollapsibleMenuProxy(mainWidget, effect); + stateMachine = new QtMaterialCollapsibleMenuStateMachine(proxy, q); + proxyStack = new QStackedLayout; + + mainWidget->setLayout(menuLayout); + menuLayout->setSpacing(0); + menuLayout->setMargin(0); + + scrollArea->setLineWidth(0); + scrollArea->setMidLineWidth(0); + scrollArea->setFrameShape(QFrame::NoFrame); + scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(mainWidget); + scrollArea->setVerticalScrollBar(scrollBar); + + scrollArea->setAutoFillBackground(true); + QPalette p(scrollArea->palette()); + p.setColor(QPalette::Background, Qt::white); + scrollArea->setPalette(p); + + scrollBar->setHideOnMouseOut(false); + + proxyStack->addWidget(scrollArea); + proxyStack->setSpacing(0); + proxyStack->setMargin(0); + proxyStack->addWidget(proxy); + proxyStack->setCurrentIndex(1); + + q->setLayout(proxyStack); + + effect->setBlurRadius(9); + effect->setOffset(QPoint(0, 0)); + effect->setColor(QColor(0, 0, 0, 100)); + q->setGraphicsEffect(effect); + + stateMachine->start(); +} + +/*! + * \class QtMaterialCollapsibleMenu + */ + +QtMaterialCollapsibleMenu::QtMaterialCollapsibleMenu(QWidget *parent) + : QWidget(parent), + d_ptr(new QtMaterialCollapsibleMenuPrivate(this)) +{ + d_func()->init(); +} + +QtMaterialCollapsibleMenu::~QtMaterialCollapsibleMenu() +{ +} + +void QtMaterialCollapsibleMenu::addMenuItem(const QString &text) +{ + QtMaterialMenuItem *item = new QtMaterialMenuItem; + item->setText(text); + addMenuItem(item); +} + +void QtMaterialCollapsibleMenu::addMenuItem(QtMaterialMenuItem *item) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->menuLayout->addWidget(item); + connect(item, SIGNAL(clicked(bool)), this, SLOT(menuItemClicked())); +} + +QtMaterialMenuItem *QtMaterialCollapsibleMenu::menuItemAt(int index) const +{ + Q_D(const QtMaterialCollapsibleMenu); + + QLayoutItem *item; + + if (!(item = d->menuLayout->itemAt(index))) { + return 0; + } + return static_cast(item->widget()); +} + +int QtMaterialCollapsibleMenu::itemCount() const +{ + Q_D(const QtMaterialCollapsibleMenu); + + return d->menuLayout->count(); +} + +void QtMaterialCollapsibleMenu::scrollTo(int dx, int dy) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->scrollArea->horizontalScrollBar()->setValue(dx); + d->scrollArea->verticalScrollBar()->setValue(dy); +} + +void QtMaterialCollapsibleMenu::setExpandXDuration(int duration) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->expandXAnimation()->setDuration(duration); +} + +void QtMaterialCollapsibleMenu::setExpandXEasingCurve(const QEasingCurve &curve) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->expandXAnimation()->setEasingCurve(curve); +} + +void QtMaterialCollapsibleMenu::setExpandYDuration(int duration) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->expandYAnimation()->setDuration(duration); +} + +void QtMaterialCollapsibleMenu::setExpandYEasingCurve(const QEasingCurve &curve) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->expandYAnimation()->setEasingCurve(curve); +} + +void QtMaterialCollapsibleMenu::setCollapseXDuration(int duration) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapseXAnimation()->setDuration(duration); +} + +void QtMaterialCollapsibleMenu::setCollapseXEasingCurve(const QEasingCurve &curve) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapseXAnimation()->setEasingCurve(curve); +} + +void QtMaterialCollapsibleMenu::setCollapseYDuration(int duration) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapseYAnimation()->setDuration(duration); +} + +void QtMaterialCollapsibleMenu::setCollapseYEasingCurve(const QEasingCurve &curve) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapseYAnimation()->setEasingCurve(curve); +} + +void QtMaterialCollapsibleMenu::setCollapsedXScale(qreal sx) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapsedState()->assignProperty(d->proxy, "xScale", sx); +} + +void QtMaterialCollapsibleMenu::setCollapsedYScale(qreal sy) +{ + Q_D(QtMaterialCollapsibleMenu); + + d->stateMachine->collapsedState()->assignProperty(d->proxy, "xScale", sy); +} + +void QtMaterialCollapsibleMenu::collapse() +{ + Q_D(QtMaterialCollapsibleMenu); + + d->proxyStack->setCurrentIndex(1); + d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(CollapsibleMenuCollapse)); + emit aboutToCollapse(); +} + +void QtMaterialCollapsibleMenu::expand() +{ + Q_D(QtMaterialCollapsibleMenu); + + d->proxyStack->setCurrentIndex(1); + d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(CollapsibleMenuExpand)); + emit aboutToExpand(); +} + +void QtMaterialCollapsibleMenu::menuItemClicked() +{ + Q_D(QtMaterialCollapsibleMenu); + + QWidget *widget = static_cast(sender()); + if (widget) { + int index = d->menuLayout->indexOf(widget); + emit itemClicked(index); + } +} + +void QtMaterialCollapsibleMenu::setOpaque() +{ + Q_D(QtMaterialCollapsibleMenu); + + d->proxyStack->setCurrentIndex(0); +} diff --git a/components/qtmaterialcollapsiblemenu.h b/components/qtmaterialcollapsiblemenu.h new file mode 100644 index 0000000..0cc29bc --- /dev/null +++ b/components/qtmaterialcollapsiblemenu.h @@ -0,0 +1,64 @@ +#ifndef QTMATERIALCOLLAPSIBLEMENU_H +#define QTMATERIALCOLLAPSIBLEMENU_H + +#include +#include + +class QtMaterialCollapsibleMenuPrivate; +class QtMaterialMenuItem; + +class QtMaterialCollapsibleMenu : public QWidget +{ + Q_OBJECT + +public: + explicit QtMaterialCollapsibleMenu(QWidget *parent = 0); + ~QtMaterialCollapsibleMenu(); + + void addMenuItem(const QString &text); + void addMenuItem(QtMaterialMenuItem *item); + + QtMaterialMenuItem *menuItemAt(int index) const; + int itemCount() const; + + void scrollTo(int dx, int dy); + + void setExpandXDuration(int duration); + void setExpandXEasingCurve(const QEasingCurve &curve); + + void setExpandYDuration(int duration); + void setExpandYEasingCurve(const QEasingCurve &curve); + + void setCollapseXDuration(int duration); + void setCollapseXEasingCurve(const QEasingCurve &curve); + + void setCollapseYDuration(int duration); + void setCollapseYEasingCurve(const QEasingCurve &curve); + + void setCollapsedXScale(qreal sx); + void setCollapsedYScale(qreal sy); + +signals: + void aboutToExpand(); + void aboutToCollapse(); + void wasExpanded(); + void wasCollapsed(); + void itemClicked(int index); + +public slots: + void collapse(); + void expand(); + void menuItemClicked(); + +protected slots: + void setOpaque(); + +protected: + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialCollapsibleMenu) + Q_DECLARE_PRIVATE(QtMaterialCollapsibleMenu) +}; + +#endif // QTMATERIALCOLLAPSIBLEMENU_H diff --git a/components/qtmaterialcollapsiblemenu_internal.cpp b/components/qtmaterialcollapsiblemenu_internal.cpp new file mode 100644 index 0000000..f144daf --- /dev/null +++ b/components/qtmaterialcollapsiblemenu_internal.cpp @@ -0,0 +1,145 @@ +#include "xx/qtmaterialcollapsiblemenu_internal.h" +#include +#include +#include +#include "xx/qtmaterialcollapsiblemenu.h" +#include "xxlib/qtmaterialstatetransition.h" + +/*! + * \class QtMaterialCollapsibleMenuStateMachine + * \internal + */ + +QtMaterialCollapsibleMenuStateMachine::QtMaterialCollapsibleMenuStateMachine( + QtMaterialCollapsibleMenuProxy *proxy, + QtMaterialCollapsibleMenu *parent) + : QStateMachine(parent), + m_menu(parent), + m_proxy(proxy), + m_expandedState(new QState), + m_collapsedState(new QState), + m_expandXAnimation(new QPropertyAnimation(this)), + m_expandYAnimation(new QPropertyAnimation(this)), + m_collapseXAnimation(new QPropertyAnimation(this)), + m_collapseYAnimation(new QPropertyAnimation(this)) +{ + Q_ASSERT(parent); + + addState(m_expandedState); + addState(m_collapsedState); + setInitialState(m_collapsedState); + + QtMaterialStateTransition *transition; + QPropertyAnimation *animation; + + transition = new QtMaterialStateTransition(CollapsibleMenuExpand); + transition->setTargetState(m_expandedState); + m_collapsedState->addTransition(transition); + + m_expandXAnimation->setTargetObject(m_proxy); + m_expandXAnimation->setPropertyName("xScale"); + m_expandXAnimation->setDuration(200); + m_expandXAnimation->setEasingCurve(QEasingCurve::OutQuad); + transition->addAnimation(m_expandXAnimation); + + m_expandYAnimation->setTargetObject(m_proxy); + m_expandYAnimation->setPropertyName("yScale"); + m_expandYAnimation->setDuration(600); + m_expandYAnimation->setEasingCurve(QEasingCurve::OutElastic); + transition->addAnimation(m_expandYAnimation); + + animation = new QPropertyAnimation(this); + animation->setTargetObject(m_proxy); + animation->setPropertyName("opacity"); + animation->setDuration(220); + animation->setEasingCurve(QEasingCurve::OutQuad); + transition->addAnimation(animation); + + transition = new QtMaterialStateTransition(CollapsibleMenuCollapse); + transition->setTargetState(m_collapsedState); + m_expandedState->addTransition(transition); + + m_collapseXAnimation->setTargetObject(m_proxy); + m_collapseXAnimation->setPropertyName("xScale"); + m_collapseXAnimation->setDuration(400); + m_collapseXAnimation->setEasingCurve(QEasingCurve::OutQuad); + transition->addAnimation(m_collapseXAnimation); + + m_collapseYAnimation->setTargetObject(m_proxy); + m_collapseYAnimation->setPropertyName("yScale"); + m_collapseYAnimation->setDuration(500); + m_collapseYAnimation->setEasingCurve(QEasingCurve::OutQuad); + transition->addAnimation(m_collapseYAnimation); + + m_expandedState->assignProperty(m_proxy, "xScale", 1); + m_expandedState->assignProperty(m_proxy, "yScale", 1); + m_expandedState->assignProperty(m_proxy, "opacity", 1); + + m_collapsedState->assignProperty(m_proxy, "xScale", 0.5); + m_collapsedState->assignProperty(m_proxy, "yScale", 0.05); + m_collapsedState->assignProperty(m_proxy, "opacity", 0); + + animation = new QPropertyAnimation(this); + animation->setTargetObject(m_proxy); + animation->setPropertyName("opacity"); + animation->setDuration(140); + transition->addAnimation(animation); + + connect(m_expandedState, SIGNAL(propertiesAssigned()), + m_menu, SLOT(setOpaque())); + connect(m_expandedState, SIGNAL(propertiesAssigned()), + m_menu, SIGNAL(wasExpanded())); + connect(m_collapsedState, SIGNAL(propertiesAssigned()), + m_menu, SIGNAL(wasCollapsed())); +} + +QtMaterialCollapsibleMenuStateMachine::~QtMaterialCollapsibleMenuStateMachine() +{ +} + +/*! + * \class QtMaterialCollapsibleMenuProxy + * \internal + */ + +QtMaterialCollapsibleMenuProxy::QtMaterialCollapsibleMenuProxy( + QWidget *source, + QGraphicsDropShadowEffect *effect, + QWidget *parent) + : QWidget(parent), + m_source(source), + m_effect(effect), + m_sx(0), + m_sy(0), + m_opacity(0) +{ +} + +QtMaterialCollapsibleMenuProxy::~QtMaterialCollapsibleMenuProxy() +{ +} + +QSize QtMaterialCollapsibleMenuProxy::sizeHint() const +{ + if (!m_source) { + return QWidget::sizeHint(); + } + return m_source->sizeHint(); +} + +void QtMaterialCollapsibleMenuProxy::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + QRect r(rect()); + QPixmap pm = m_source->grab(r.translated(-m_source->pos())).scaled( + static_cast(r.width())*m_sx, + static_cast(r.height())*m_sy, + Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + + painter.setOpacity(m_opacity); + painter.drawPixmap(0, 0, pm); +} diff --git a/components/qtmaterialcollapsiblemenu_internal.h b/components/qtmaterialcollapsiblemenu_internal.h new file mode 100644 index 0000000..582684e --- /dev/null +++ b/components/qtmaterialcollapsiblemenu_internal.h @@ -0,0 +1,147 @@ +#ifndef QTMATERIALCOLLAPSIBLEMENU_INTERNAL_H +#define QTMATERIALCOLLAPSIBLEMENU_INTERNAL_H + +#include +#include +#include +#include + +class QState; +class QPropertyAnimation; +class QtMaterialCollapsibleMenu; +class QtMaterialCollapsibleMenuProxy; + +class QtMaterialCollapsibleMenuStateMachine : public QStateMachine +{ + Q_OBJECT + +public: + QtMaterialCollapsibleMenuStateMachine(QtMaterialCollapsibleMenuProxy *proxy, QtMaterialCollapsibleMenu *parent); + ~QtMaterialCollapsibleMenuStateMachine(); + + inline QState *expandedState() const; + inline QState *collapsedState() const; + inline QPropertyAnimation *expandXAnimation() const; + inline QPropertyAnimation *expandYAnimation() const; + inline QPropertyAnimation *collapseXAnimation() const; + inline QPropertyAnimation *collapseYAnimation() const; + +private: + Q_DISABLE_COPY(QtMaterialCollapsibleMenuStateMachine) + + QtMaterialCollapsibleMenu *const m_menu; + QtMaterialCollapsibleMenuProxy *const m_proxy; + QState *const m_expandedState; + QState *const m_collapsedState; + QPropertyAnimation *const m_expandXAnimation; + QPropertyAnimation *const m_expandYAnimation; + QPropertyAnimation *const m_collapseXAnimation; + QPropertyAnimation *const m_collapseYAnimation; +}; + +inline QState *QtMaterialCollapsibleMenuStateMachine::expandedState() const +{ + return m_expandedState; +} + +inline QState *QtMaterialCollapsibleMenuStateMachine::collapsedState() const +{ + return m_collapsedState; +} + +inline QPropertyAnimation *QtMaterialCollapsibleMenuStateMachine::expandXAnimation() const +{ + return m_expandXAnimation; +} + +inline QPropertyAnimation *QtMaterialCollapsibleMenuStateMachine::expandYAnimation() const +{ + return m_expandYAnimation; +} + +inline QPropertyAnimation *QtMaterialCollapsibleMenuStateMachine::collapseXAnimation() const +{ + return m_collapseXAnimation; +} + +inline QPropertyAnimation *QtMaterialCollapsibleMenuStateMachine::collapseYAnimation() const +{ + return m_collapseYAnimation; +} + +class QGraphicsDropShadowEffect; + +class QtMaterialCollapsibleMenuProxy : public QWidget +{ + Q_OBJECT + + 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: + QtMaterialCollapsibleMenuProxy(QWidget *source, QGraphicsDropShadowEffect *effect, QWidget *parent = 0); + ~QtMaterialCollapsibleMenuProxy(); + + QSize sizeHint() const Q_DECL_OVERRIDE; + + inline void setXScale(qreal sx); + inline qreal xScale() const; + + inline void setYScale(qreal sy); + inline qreal yScale() const; + + inline void setOpacity(qreal opacity); + inline qreal opacity() const; + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialCollapsibleMenuProxy) + + QWidget *const m_source; + QGraphicsDropShadowEffect *const m_effect; + qreal m_sx; + qreal m_sy; + qreal m_opacity; +}; + +inline void QtMaterialCollapsibleMenuProxy::setXScale(qreal sx) +{ + m_sx = sx; + update(); + m_effect->update(); +} + +inline qreal QtMaterialCollapsibleMenuProxy::xScale() const +{ + return m_sx; +} + +inline void QtMaterialCollapsibleMenuProxy::setYScale(qreal sy) +{ + m_sy = sy; + update(); + m_effect->update(); +} + +inline qreal QtMaterialCollapsibleMenuProxy::yScale() const +{ + return m_sy; +} + +inline void QtMaterialCollapsibleMenuProxy::setOpacity(qreal opacity) +{ + m_opacity = opacity; + m_effect->setColor(QColor(0, 0, 0, 100*(pow(opacity, 5)))); + m_effect->update(); + update(); +} + +inline qreal QtMaterialCollapsibleMenuProxy::opacity() const +{ + return m_opacity; +} + +#endif // QTMATERIALCOLLAPSIBLEMENU_INTERNAL_H diff --git a/components/qtmaterialcollapsiblemenu_p.h b/components/qtmaterialcollapsiblemenu_p.h new file mode 100644 index 0000000..5684be1 --- /dev/null +++ b/components/qtmaterialcollapsiblemenu_p.h @@ -0,0 +1,34 @@ +#ifndef QTMATERIALCOLLAPSIBLEMENU_P_H +#define QTMATERIALCOLLAPSIBLEMENU_P_H + +#include + +class QScrollArea; +class QWidget; +class QVBoxLayout; +class QStackedLayout; +class QtMaterialCollapsibleMenu; +class QtMaterialCollapsibleMenuStateMachine; +class QtMaterialCollapsibleMenuProxy; + +class QtMaterialCollapsibleMenuPrivate +{ + Q_DISABLE_COPY(QtMaterialCollapsibleMenuPrivate) + Q_DECLARE_PUBLIC(QtMaterialCollapsibleMenu) + +public: + QtMaterialCollapsibleMenuPrivate(QtMaterialCollapsibleMenu *q); + ~QtMaterialCollapsibleMenuPrivate(); + + void init(); + + QtMaterialCollapsibleMenu *const q_ptr; + QScrollArea *scrollArea; + QWidget *mainWidget; + QVBoxLayout *menuLayout; + QtMaterialCollapsibleMenuProxy *proxy; + QtMaterialCollapsibleMenuStateMachine *stateMachine; + QStackedLayout *proxyStack; +}; + +#endif // QTMATERIALCOLLAPSIBLEMENU_P_H diff --git a/components/qtmaterialmenuitem.cpp b/components/qtmaterialmenuitem.cpp new file mode 100644 index 0000000..c2c9f57 --- /dev/null +++ b/components/qtmaterialmenuitem.cpp @@ -0,0 +1,115 @@ +#include "xx/qtmaterialmenuitem.h" +#include "xx/qtmaterialmenuitem_p.h" +#include +#include "xx/qtmaterialmenuitem_internal.h" +#include "xxlib/qtmaterialstyle.h" + +/*! + * \class QtMaterialMenuItemPrivate + * \internal + */ + +/*! + * \internal + */ +QtMaterialMenuItemPrivate::QtMaterialMenuItemPrivate(QtMaterialMenuItem *q) + : QtMaterialFlatButtonPrivate(q) +{ +} + +/*! + * \internal + */ +QtMaterialMenuItemPrivate::~QtMaterialMenuItemPrivate() +{ +} + +/*! + * \internal + */ +void QtMaterialMenuItemPrivate::init() +{ + Q_Q(QtMaterialMenuItem); + + highlighted = false; + + QFont font(q->font()); + font.setCapitalization(QFont::MixedCase); + font.setPointSize(11); + font.setStyleName("Regular"); + q->setFont(font); + + q->setOverlayStyle(XXMaterial::GrayOverlay); + q->setForegroundColor(QtMaterialStyle::instance().themeColor("text")); + q->setCornerRadius(0); +} + +/*! + * \class QtMaterialMenuItem + */ + +QtMaterialMenuItem::QtMaterialMenuItem(QWidget *parent) + : QtMaterialFlatButton(*new QtMaterialMenuItemPrivate(this), parent) +{ + d_func()->init(); +} + +QtMaterialMenuItem::~QtMaterialMenuItem() +{ +} + +void QtMaterialMenuItem::setHighlighted(bool value) +{ + Q_D(QtMaterialMenuItem); + + d->highlighted = value; +} + +bool QtMaterialMenuItem::isHighlighted() const +{ + Q_D(const QtMaterialMenuItem); + + return d->highlighted; +} + +void QtMaterialMenuItem::paintForeground(QPainter *painter) +{ + if (isEnabled()) { + painter->setPen(foregroundColor()); + } else { + painter->setPen(disabledForegroundColor()); + } + + QRect r(rect()); + + if (icon().isNull()) { + painter->drawText(r.marginsRemoved(QMargins(14, 0, 14, 0)), + Qt::AlignVCenter | Qt::AlignLeft, + text()); + return; + } + + QSize textSize(fontMetrics().size(Qt::TextSingleLine, text())); + QSize base(size()-textSize); + + const int iw = iconSize().width() + IconPadding; + + QRect textGeometry(QPoint(14, base.height()/2), textSize); + QRect iconGeometry(QPoint(14, (height()-iconSize().height())/2), iconSize()); + + if (XXMaterial::LeftIcon == iconPlacement()) { + textGeometry.translate(iw, 0); + } else { + iconGeometry.translate(textSize.width() + IconPadding, 0); + } + + painter->drawText(textGeometry, + Qt::AlignVCenter | Qt::AlignLeft, + 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); +} diff --git a/components/qtmaterialmenuitem.h b/components/qtmaterialmenuitem.h new file mode 100644 index 0000000..9239556 --- /dev/null +++ b/components/qtmaterialmenuitem.h @@ -0,0 +1,27 @@ +#ifndef QTMATERIALMENUITEM_H +#define QTMATERIALMENUITEM_H + +#include "xx/qtmaterialflatbutton.h" + +class QtMaterialMenuItemPrivate; + +class QtMaterialMenuItem : public QtMaterialFlatButton +{ + Q_OBJECT + +public: + explicit QtMaterialMenuItem(QWidget *parent = 0); + ~QtMaterialMenuItem(); + + void setHighlighted(bool value); + bool isHighlighted() const; + +protected: + void paintForeground(QPainter *painter) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialMenuItem) + Q_DECLARE_PRIVATE(QtMaterialMenuItem) +}; + +#endif // QTMATERIALMENUITEM_H diff --git a/components/qtmaterialmenuitem_internal.cpp b/components/qtmaterialmenuitem_internal.cpp new file mode 100644 index 0000000..0f106da --- /dev/null +++ b/components/qtmaterialmenuitem_internal.cpp @@ -0,0 +1,50 @@ +#include "xx/qtmaterialmenuitem_internal.h" +#include +#include + +/*! + * \class QtMaterialMenuItemStateMachine + * \internal + */ + +/*! + * \internal + */ +QtMaterialMenuItemStateMachine::QtMaterialMenuItemStateMachine(QtMaterialMenuItem *menuItem) + : QStateMachine(menuItem), + m_menuItem(menuItem), + m_defaultState(new QState), + m_highlightedState(new QState) +{ + Q_ASSERT(menuItem); + + addState(m_defaultState); + addState(m_highlightedState); + + setInitialState(m_defaultState); + + QSignalTransition *transition; + + transition = new QSignalTransition(this, SIGNAL(highlight())); + transition->setTargetState(m_highlightedState); + m_defaultState->addTransition(transition); + + transition = new QSignalTransition(this, SIGNAL(unhighlight())); + transition->setTargetState(m_defaultState); + m_highlightedState->addTransition(transition); + + QPropertyAnimation *animation; + + animation = new QPropertyAnimation(this); + animation->setTargetObject(this); + animation->setPropertyName("foregroundColor"); + animation->setDuration(160); + addDefaultAnimation(animation); +} + +/*! + * \internal + */ +QtMaterialMenuItemStateMachine::~QtMaterialMenuItemStateMachine() +{ +} diff --git a/components/qtmaterialmenuitem_internal.h b/components/qtmaterialmenuitem_internal.h new file mode 100644 index 0000000..ec62fbe --- /dev/null +++ b/components/qtmaterialmenuitem_internal.h @@ -0,0 +1,47 @@ +#ifndef QTMATERIALMENUITEM_INTERNAL_H +#define QTMATERIALMENUITEM_INTERNAL_H + +#include +#include +#include "xx/qtmaterialmenuitem.h" + +class QtMaterialMenuItem; + +class QtMaterialMenuItemStateMachine : public QStateMachine +{ + Q_OBJECT + + Q_PROPERTY(QColor foregroundColor READ foregroundColor WRITE setForegroundColor) + +public: + explicit QtMaterialMenuItemStateMachine(QtMaterialMenuItem *menuItem); + ~QtMaterialMenuItemStateMachine(); + + inline void setForegroundColor(const QColor &color); + inline QColor foregroundColor() const; + +signals: + void highlight(); + void unhighlight(); + +private: + Q_DISABLE_COPY(QtMaterialMenuItemStateMachine) + + QtMaterialMenuItem *const m_menuItem; + QState *const m_defaultState; + QState *const m_highlightedState; + QColor m_foregroundColor; +}; + +inline void QtMaterialMenuItemStateMachine::setForegroundColor(const QColor &color) +{ + m_foregroundColor = color; + m_menuItem->update(); +} + +inline QColor QtMaterialMenuItemStateMachine::foregroundColor() const +{ + return m_foregroundColor; +} + +#endif // QTMATERIALMENUITEM_INTERNAL_H diff --git a/components/qtmaterialmenuitem_p.h b/components/qtmaterialmenuitem_p.h new file mode 100644 index 0000000..c4f8718 --- /dev/null +++ b/components/qtmaterialmenuitem_p.h @@ -0,0 +1,23 @@ +#ifndef QTMATERIALMENUITEM_P_H +#define QTMATERIALMENUITEM_P_H + +#include "xx/qtmaterialflatbutton_p.h" + +class QtMaterialMenuItem; +class QtMaterialMenuItemStateMachine; + +class QtMaterialMenuItemPrivate : public QtMaterialFlatButtonPrivate +{ + Q_DISABLE_COPY(QtMaterialMenuItemPrivate) + Q_DECLARE_PUBLIC(QtMaterialMenuItem) + +public: + QtMaterialMenuItemPrivate(QtMaterialMenuItem *q); + ~QtMaterialMenuItemPrivate(); + + void init(); + + bool highlighted; +}; + +#endif // QTMATERIALMENUITEM_P_H diff --git a/components/qtmaterialselectfield.cpp b/components/qtmaterialselectfield.cpp index 25299d1..a0b6574 100644 --- a/components/qtmaterialselectfield.cpp +++ b/components/qtmaterialselectfield.cpp @@ -1,14 +1,14 @@ -#include "xx/qtmaterialselectfield.h" -#include "xx/qtmaterialselectfield_p.h" +#include "qtmaterialselectfield.h" +#include "qtmaterialselectfield_p.h" #include #include #include #include #include -#include "xxlib/qtmaterialstyle.h" -#include "xx/qtmaterialmenuitem.h" -#include "xx/qtmaterialcollapsiblemenu.h" -#include "xxlib/qtmaterialoverlaywidget.h" +#include "lib/qtmaterialstyle.h" +#include "qtmaterialmenuitem.h" +#include "qtmaterialcollapsiblemenu.h" +#include "lib/qtmaterialoverlaywidget.h" /*! * \class QtMaterialSelectFieldPrivate diff --git a/components/qtmaterialselectfield.h b/components/qtmaterialselectfield.h index fc263e4..bcc5a0f 100644 --- a/components/qtmaterialselectfield.h +++ b/components/qtmaterialselectfield.h @@ -1,7 +1,7 @@ #ifndef QTMATERIALSELECTFIELD_H #define QTMATERIALSELECTFIELD_H -#include +#include class QtMaterialSelectFieldPrivate; class QtMaterialMenuItem; diff --git a/examples/examples.pro b/examples/examples.pro index 57cdd85..db94f02 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -16,7 +16,8 @@ SOURCES = mainwindow.cpp \ radiobuttonsettingseditor.cpp \ togglesettingseditor.cpp \ textfieldsettingseditor.cpp \ - tabssettingseditor.cpp + tabssettingseditor.cpp \ + selectfieldsettingseditor.cpp HEADERS = mainwindow.h \ avatarsettingseditor.h \ badgesettingseditor.h \ @@ -33,7 +34,8 @@ HEADERS = mainwindow.h \ radiobuttonsettingseditor.h \ togglesettingseditor.h \ textfieldsettingseditor.h \ - tabssettingseditor.h + tabssettingseditor.h \ + selectfieldsettingseditor.h LIBS += ../components/libcomponents.a INCLUDEPATH += ../components/ TARGET = ../examples-exe @@ -53,4 +55,5 @@ FORMS += \ slidersettingsform.ui \ radiobuttonsettingsform.ui \ togglesettingsform.ui \ - textfieldsettingsform.ui + textfieldsettingsform.ui \ + selectfieldsettingsform.ui diff --git a/examples/mainwindow.cpp b/examples/mainwindow.cpp index 81795c5..429b73d 100644 --- a/examples/mainwindow.cpp +++ b/examples/mainwindow.cpp @@ -16,6 +16,7 @@ #include "togglesettingseditor.h" #include "textfieldsettingseditor.h" #include "tabssettingseditor.h" +#include "selectfieldsettingseditor.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) @@ -49,6 +50,7 @@ MainWindow::MainWindow(QWidget *parent) ToggleSettingsEditor *toggle = new ToggleSettingsEditor; TextFieldSettingsEditor *textField = new TextFieldSettingsEditor; TabsSettingsEditor *tabs = new TabsSettingsEditor; + SelectFieldSettingsEditor *selectField = new SelectFieldSettingsEditor; stack->addWidget(avatar); stack->addWidget(badge); @@ -60,6 +62,7 @@ MainWindow::MainWindow(QWidget *parent) stack->addWidget(progress); stack->addWidget(radioButton); stack->addWidget(raisedButton); + stack->addWidget(selectField); stack->addWidget(slider); stack->addWidget(tabs); stack->addWidget(textField); @@ -75,6 +78,7 @@ MainWindow::MainWindow(QWidget *parent) list->addItem("Progress"); list->addItem("Radio Button"); list->addItem("Raised Button"); + list->addItem("Select Field"); list->addItem("Slider"); list->addItem("Tabs"); list->addItem("Text Field");