diff --git a/components/qtmaterialiconmenu.cpp b/components/qtmaterialiconmenu.cpp new file mode 100644 index 0000000..0a41741 --- /dev/null +++ b/components/qtmaterialiconmenu.cpp @@ -0,0 +1,169 @@ +#include "xx/qtmaterialiconmenu.h" +#include "xx/qtmaterialiconmenu_p.h" +#include +#include +#include "xxlib/qtmaterialoverlaywidget.h" +#include "xx/qtmaterialcollapsiblemenu.h" + +/*! + * \class QtMaterialIconMenuPrivate + * \internal + */ + +QtMaterialIconMenuPrivate::QtMaterialIconMenuPrivate(QtMaterialIconMenu *q) + : QtMaterialIconButtonPrivate(q) +{ +} + +QtMaterialIconMenuPrivate::~QtMaterialIconMenuPrivate() +{ +} + +void QtMaterialIconMenuPrivate::init() +{ + Q_Q(QtMaterialIconMenu); + + menuOverlay = new QtMaterialOverlayWidget(q); + menu = new QtMaterialCollapsibleMenu; + autoCollapse = true; + + menuOverlay->setParent(q->parentWidget()); + menuOverlay->setAttribute(Qt::WA_TransparentForMouseEvents); + menuOverlay->installEventFilter(q); + + menu->setParent(menuOverlay); + menu->setMaximumHeight(300); + menu->setMinimumWidth(200); + + QObject::connect(menu, SIGNAL(aboutToCollapse()), q, SLOT(makeTransparent())); + QObject::connect(menu, SIGNAL(wasExpanded()), q, SLOT(makeOpaque())); + QObject::connect(menu, SIGNAL(aboutToExpand()), menuOverlay, SLOT(raise())); + QObject::connect(menu, SIGNAL(itemClicked(int)), q, SIGNAL(itemSelected(int))); + QObject::connect(menu, SIGNAL(itemClicked(int)), q, SLOT(collapseDelayed())); +} + +/*! + * \class QtMaterialIconMenu + */ + +QtMaterialIconMenu::QtMaterialIconMenu(const QIcon &icon, QWidget *parent) + : QtMaterialIconButton(*new QtMaterialIconMenuPrivate(this), parent) +{ + d_func()->init(); + + setIcon(icon); +} + +QtMaterialIconMenu::~QtMaterialIconMenu() +{ +} + +void QtMaterialIconMenu::addMenuItem(const QString &text) +{ + Q_D(QtMaterialIconMenu); + + d->menu->addMenuItem(text); +} + +void QtMaterialIconMenu::addMenuItem(QtMaterialMenuItem *item) +{ + Q_D(QtMaterialIconMenu); + + d->menu->addMenuItem(item); +} + +QtMaterialMenuItem *QtMaterialIconMenu::itemAt(int index) const +{ + Q_D(const QtMaterialIconMenu); + + return d->menu->menuItemAt(index); +} + +void QtMaterialIconMenu::setAutoCollapse(bool value) +{ + Q_D(QtMaterialIconMenu); + + d->autoCollapse = value; +} + +bool QtMaterialIconMenu::autoCollapse() const +{ + Q_D(const QtMaterialIconMenu); + + return d->autoCollapse; +} + +void QtMaterialIconMenu::makeTransparent() +{ + Q_D(QtMaterialIconMenu); + + d->menuOverlay->setAttribute(Qt::WA_TransparentForMouseEvents, true); +} + +void QtMaterialIconMenu::makeOpaque() +{ + Q_D(QtMaterialIconMenu); + + d->menuOverlay->setAttribute(Qt::WA_TransparentForMouseEvents, false); +} + +void QtMaterialIconMenu::collapseDelayed() +{ + Q_D(QtMaterialIconMenu); + + if (d->autoCollapse) { + QTimer::singleShot(110, d->menu, SLOT(collapse())); + } +} + +/*! + * \reimp + */ +bool QtMaterialIconMenu::event(QEvent *event) +{ + Q_D(QtMaterialIconMenu); + + switch (event->type()) + { + case QEvent::Move: + case QEvent::Resize: + { + const QSize sh = d->menu->sizeHint(); + QPoint p = pos(); + p += QPoint(width()/2, height()/2); + d->menu->setGeometry(p.x(), p.y(), sh.width(), sh.height()); + break; + } + case QEvent::MouseButtonRelease: + { + if (isEnabled()) { + d->menu->expand(); + } + break; + } + case QEvent::ParentChange: + { + QWidget *widget; + if ((widget = parentWidget())) { + d->menuOverlay->setParent(widget); + } + break; + } + default: + break; + } + return QtMaterialIconButton::event(event); +} + +/*! + * \reimp + */ +bool QtMaterialIconMenu::eventFilter(QObject *obj, QEvent *event) +{ + Q_D(QtMaterialIconMenu); + + if (QEvent::MouseButtonPress == event->type()) { + d->menu->collapse(); + } + return QtMaterialIconButton::eventFilter(obj, event); +} diff --git a/components/qtmaterialiconmenu.h b/components/qtmaterialiconmenu.h new file mode 100644 index 0000000..9468cac --- /dev/null +++ b/components/qtmaterialiconmenu.h @@ -0,0 +1,42 @@ +#ifndef QTMATERIALICONMENU_H +#define QTMATERIALICONMENU_H + +#include "xx/qtmaterialiconbutton.h" + +class QtMaterialIconMenuPrivate; +class QtMaterialMenuItem; + +class QtMaterialIconMenu : public QtMaterialIconButton +{ + Q_OBJECT + +public: + explicit QtMaterialIconMenu(const QIcon &icon, QWidget *parent = 0); + ~QtMaterialIconMenu(); + + void addMenuItem(const QString &text); + void addMenuItem(QtMaterialMenuItem *item); + + QtMaterialMenuItem *itemAt(int index) const; + + void setAutoCollapse(bool value); + bool autoCollapse() const; + +signals: + void itemSelected(int index); + +protected slots: + void makeTransparent(); + void makeOpaque(); + void collapseDelayed(); + +protected: + bool event(QEvent *event) Q_DECL_OVERRIDE; + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; + +private: + Q_DISABLE_COPY(QtMaterialIconMenu) + Q_DECLARE_PRIVATE(QtMaterialIconMenu) +}; + +#endif // QTMATERIALICONMENU_H diff --git a/components/qtmaterialiconmenu_p.h b/components/qtmaterialiconmenu_p.h new file mode 100644 index 0000000..3cfda43 --- /dev/null +++ b/components/qtmaterialiconmenu_p.h @@ -0,0 +1,26 @@ +#ifndef QTMATERIALICONMENU_P_H +#define QTMATERIALICONMENU_P_H + +#include "xx/qtmaterialiconbutton_p.h" + +class QtMaterialIconMenu; +class QtMaterialOverlayWidget; +class QtMaterialCollapsibleMenu; + +class QtMaterialIconMenuPrivate : public QtMaterialIconButtonPrivate +{ + Q_DISABLE_COPY(QtMaterialIconMenuPrivate) + Q_DECLARE_PUBLIC(QtMaterialIconMenu) + +public: + QtMaterialIconMenuPrivate(QtMaterialIconMenu *q); + ~QtMaterialIconMenuPrivate(); + + void init(); + + QtMaterialOverlayWidget *menuOverlay; + QtMaterialCollapsibleMenu *menu; + bool autoCollapse; +}; + +#endif // QTMATERIALICONMENU_P_H diff --git a/examples/iconmenusettingseditor.cpp b/examples/iconmenusettingseditor.cpp new file mode 100644 index 0000000..4db69db --- /dev/null +++ b/examples/iconmenusettingseditor.cpp @@ -0,0 +1,87 @@ +#include "yy/iconmenusettingseditor.h" +#include +#include +#include +#include "xx/qtmaterialiconmenu.h" +#include "xx/qtmaterialmenuitem.h" + +IconMenuSettingsEditor::IconMenuSettingsEditor(QWidget *parent) + : QWidget(parent), + ui(new Ui::IconMenuSettingsForm), + m_iconMenu(new QtMaterialIconMenu(QIcon("../qt-material-widgets/ic_star_black_24px.svg"))) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + + QWidget *widget = new QWidget; + layout->addWidget(widget); + + QWidget *canvas = new QWidget; + canvas->setStyleSheet("QWidget { background: white; }"); + layout->addWidget(canvas); + + ui->setupUi(widget); + layout->setContentsMargins(20, 20, 20, 20); + + layout = new QVBoxLayout; + canvas->setLayout(layout); + layout->addWidget(m_iconMenu); + layout->setAlignment(m_iconMenu, Qt::AlignCenter); + + { + m_iconMenu->addMenuItem("C"); + m_iconMenu->addMenuItem("C++"); + m_iconMenu->addMenuItem("PHP"); + m_iconMenu->addMenuItem("Haskell"); + m_iconMenu->addMenuItem("JavaScript"); + m_iconMenu->addMenuItem("ECMAScript"); + m_iconMenu->addMenuItem("OCaml"); + m_iconMenu->addMenuItem("Python"); + m_iconMenu->addMenuItem("F#"); + m_iconMenu->addMenuItem("Clojure"); + m_iconMenu->addMenuItem("Java"); + + m_iconMenu->itemAt(2)->setDisabled(true); + } + + setupForm(); + + connect(ui->disabledCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateWidget())); + connect(ui->autoCollapseCheckBox, SIGNAL(toggled(bool)), this, SLOT(updateWidget())); + connect(ui->colorToolButton, SIGNAL(clicked(bool)), this, SLOT(selectColor())); + connect(ui->disabledColorToolButton, SIGNAL(clicked(bool)), this, SLOT(selectColor())); +} + +IconMenuSettingsEditor::~IconMenuSettingsEditor() +{ + delete ui; +} + +void IconMenuSettingsEditor::setupForm() +{ + ui->disabledCheckBox->setChecked(!m_iconMenu->isEnabled()); + ui->autoCollapseCheckBox->setChecked(m_iconMenu->autoCollapse()); +} + +void IconMenuSettingsEditor::updateWidget() +{ + m_iconMenu->setDisabled(ui->disabledCheckBox->isChecked()); + m_iconMenu->setAutoCollapse(ui->autoCollapseCheckBox->isChecked()); +} + +void IconMenuSettingsEditor::selectColor() +{ + QColorDialog dialog; + if (dialog.exec()) { + QColor color = dialog.selectedColor(); + QString senderName = sender()->objectName(); + if ("colorToolButton" == senderName) { + m_iconMenu->setColor(color); + ui->colorLineEdit->setText(color.name(QColor::HexRgb)); + } else if ("disabledColorToolButton" == senderName) { + m_iconMenu->setDisabledColor(color); + ui->disabledColorLineEdit->setText(color.name(QColor::HexRgb)); + } + } + setupForm(); +} diff --git a/examples/iconmenusettingseditor.h b/examples/iconmenusettingseditor.h new file mode 100644 index 0000000..89c5d44 --- /dev/null +++ b/examples/iconmenusettingseditor.h @@ -0,0 +1,27 @@ +#ifndef ICONMENUSETTINGSEDITOR_H +#define ICONMENUSETTINGSEDITOR_H + +#include +#include "ui_iconmenusettingsform.h" + +class QtMaterialIconMenu; + +class IconMenuSettingsEditor : public QWidget +{ + Q_OBJECT + +public: + explicit IconMenuSettingsEditor(QWidget *parent = 0); + ~IconMenuSettingsEditor(); + +protected slots: + void setupForm(); + void updateWidget(); + void selectColor(); + +private: + Ui::IconMenuSettingsForm *const ui; + QtMaterialIconMenu *const m_iconMenu; +}; + +#endif // ICONMENUSETTINGSEDITOR_H diff --git a/examples/iconmenusettingsform.ui b/examples/iconmenusettingsform.ui new file mode 100644 index 0000000..a3c2674 --- /dev/null +++ b/examples/iconmenusettingsform.ui @@ -0,0 +1,101 @@ + + + IconMenuSettingsForm + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + 0 + 0 + 160 + 104 + + + + + + + Disabled + + + + + + + + + + Color + + + + + + + Auto collapse + + + + + + + + + + + + false + + + + + + + ... + + + + + + + + + Disabled color + + + + + + + + + false + + + + + + + ... + + + + + + + + + + +