420 lines
11 KiB
C++
420 lines
11 KiB
C++
|
#include "lib/qtmaterialcheckable.h"
|
||
|
#include "lib/qtmaterialcheckable_p.h"
|
||
|
#include <QPainter>
|
||
|
#include <QEvent>
|
||
|
#include <QStateMachine>
|
||
|
#include <QSignalTransition>
|
||
|
#include <QEventTransition>
|
||
|
#include <QColor>
|
||
|
#include <QCoreApplication>
|
||
|
#include "lib/qtmaterialrippleoverlay.h"
|
||
|
#include "lib/qtmaterialripple.h"
|
||
|
#include "lib/qtmaterialstyle.h"
|
||
|
#include "lib/qtmaterialcheckable_internal.h"
|
||
|
|
||
|
/*!
|
||
|
* \class QtMaterialCheckablePrivate
|
||
|
* \internal
|
||
|
*/
|
||
|
|
||
|
QtMaterialCheckablePrivate::QtMaterialCheckablePrivate(QtMaterialCheckable *q)
|
||
|
: q_ptr(q)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
QtMaterialCheckablePrivate::~QtMaterialCheckablePrivate()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckablePrivate::init()
|
||
|
{
|
||
|
Q_Q(QtMaterialCheckable);
|
||
|
|
||
|
rippleOverlay = new QtMaterialRippleOverlay;
|
||
|
checkedIcon = new QtMaterialCheckableIcon(QIcon(":/icons/icons/toggle/svg/production/ic_check_box_24px.svg"), q);
|
||
|
uncheckedIcon = new QtMaterialCheckableIcon(QIcon(":/icons/icons/toggle/svg/production/ic_check_box_outline_blank_24px.svg"), q);
|
||
|
stateMachine = new QStateMachine(q);
|
||
|
uncheckedState = new QState;
|
||
|
checkedState = new QState;
|
||
|
disabledUncheckedState = new QState;
|
||
|
disabledCheckedState = new QState;
|
||
|
uncheckedTransition = new QSignalTransition(q, SIGNAL(toggled(bool)));
|
||
|
checkedTransition = new QSignalTransition(q, SIGNAL(toggled(bool)));
|
||
|
labelPosition = QtMaterialCheckable::LabelPositionRight;
|
||
|
useThemeColors = true;
|
||
|
|
||
|
rippleOverlay->setParent(q->parentWidget());
|
||
|
rippleOverlay->installEventFilter(q);
|
||
|
|
||
|
q->setCheckable(true);
|
||
|
q->setStyle(&QtMaterialStyle::instance());
|
||
|
q->setFont(QFont("Roboto", 11, QFont::Normal));
|
||
|
|
||
|
stateMachine->addState(uncheckedState);
|
||
|
stateMachine->addState(checkedState);
|
||
|
stateMachine->addState(disabledUncheckedState);
|
||
|
stateMachine->addState(disabledCheckedState);
|
||
|
stateMachine->setInitialState(uncheckedState);
|
||
|
|
||
|
// Transition to checked
|
||
|
|
||
|
uncheckedTransition->setTargetState(checkedState);
|
||
|
uncheckedState->addTransition(uncheckedTransition);
|
||
|
|
||
|
// Transition to unchecked
|
||
|
|
||
|
checkedTransition->setTargetState(uncheckedState);
|
||
|
checkedState->addTransition(checkedTransition);
|
||
|
|
||
|
QAbstractTransition *transition;
|
||
|
|
||
|
// Transitions enabled <==> disabled
|
||
|
|
||
|
transition = new QEventTransition(q, QEvent::EnabledChange);
|
||
|
transition->setTargetState(disabledUncheckedState);
|
||
|
uncheckedState->addTransition(transition);
|
||
|
|
||
|
transition = new QEventTransition(q, QEvent::EnabledChange);
|
||
|
transition->setTargetState(uncheckedState);
|
||
|
disabledUncheckedState->addTransition(transition);
|
||
|
|
||
|
transition = new QEventTransition(q, QEvent::EnabledChange);
|
||
|
transition->setTargetState(disabledCheckedState);
|
||
|
checkedState->addTransition(transition);
|
||
|
|
||
|
transition = new QEventTransition(q, QEvent::EnabledChange);
|
||
|
transition->setTargetState(checkedState);
|
||
|
disabledCheckedState->addTransition(transition);
|
||
|
|
||
|
transition = new QSignalTransition(q, SIGNAL(toggled(bool)));
|
||
|
transition->setTargetState(disabledCheckedState);
|
||
|
disabledUncheckedState->addTransition(transition);
|
||
|
|
||
|
transition = new QSignalTransition(q, SIGNAL(toggled(bool)));
|
||
|
transition->setTargetState(disabledUncheckedState);
|
||
|
disabledCheckedState->addTransition(transition);
|
||
|
|
||
|
//
|
||
|
|
||
|
checkedState->assignProperty(checkedIcon, "opacity", 1);
|
||
|
checkedState->assignProperty(uncheckedIcon, "opacity", 0);
|
||
|
|
||
|
uncheckedState->assignProperty(checkedIcon, "opacity", 0);
|
||
|
uncheckedState->assignProperty(uncheckedIcon, "opacity", 1);
|
||
|
|
||
|
disabledCheckedState->assignProperty(checkedIcon, "opacity", 1);
|
||
|
disabledCheckedState->assignProperty(uncheckedIcon, "opacity", 0);
|
||
|
|
||
|
disabledUncheckedState->assignProperty(checkedIcon, "opacity", 0);
|
||
|
disabledUncheckedState->assignProperty(uncheckedIcon, "opacity", 1);
|
||
|
|
||
|
checkedState->assignProperty(checkedIcon, "color", q->checkedColor());
|
||
|
checkedState->assignProperty(uncheckedIcon, "color", q->checkedColor());
|
||
|
|
||
|
uncheckedState->assignProperty(uncheckedIcon, "color", q->uncheckedColor());
|
||
|
uncheckedState->assignProperty(uncheckedIcon, "color", q->uncheckedColor());
|
||
|
|
||
|
disabledUncheckedState->assignProperty(uncheckedIcon, "color", q->disabledColor());
|
||
|
disabledCheckedState->assignProperty(checkedIcon, "color", q->disabledColor());
|
||
|
|
||
|
stateMachine->start();
|
||
|
QCoreApplication::processEvents();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \class QtMaterialCheckable
|
||
|
*/
|
||
|
|
||
|
QtMaterialCheckable::QtMaterialCheckable(QWidget *parent)
|
||
|
: QAbstractButton(parent),
|
||
|
d_ptr(new QtMaterialCheckablePrivate(this))
|
||
|
{
|
||
|
d_func()->init();
|
||
|
}
|
||
|
|
||
|
QtMaterialCheckable::~QtMaterialCheckable()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setLabelPosition(LabelPosition placement)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->labelPosition = placement;
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
QtMaterialCheckable::LabelPosition QtMaterialCheckable::labelPosition() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
return d->labelPosition;
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setUseThemeColors(bool value)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
if (d->useThemeColors == value) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
d->useThemeColors = value;
|
||
|
setupProperties();
|
||
|
}
|
||
|
|
||
|
bool QtMaterialCheckable::useThemeColors() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
return d->useThemeColors;
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setCheckedColor(const QColor &color)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->checkedColor = color;
|
||
|
|
||
|
MATERIAL_DISABLE_THEME_COLORS
|
||
|
setupProperties();
|
||
|
}
|
||
|
|
||
|
QColor QtMaterialCheckable::checkedColor() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
if (d->useThemeColors || !d->checkedColor.isValid()) {
|
||
|
return QtMaterialStyle::instance().themeColor("primary1");
|
||
|
} else {
|
||
|
return d->checkedColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setUncheckedColor(const QColor &color)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->uncheckedColor = color;
|
||
|
|
||
|
MATERIAL_DISABLE_THEME_COLORS
|
||
|
setupProperties();
|
||
|
}
|
||
|
|
||
|
QColor QtMaterialCheckable::uncheckedColor() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
if (d->useThemeColors || !d->uncheckedColor.isValid()) {
|
||
|
return QtMaterialStyle::instance().themeColor("text");
|
||
|
} else {
|
||
|
return d->uncheckedColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setTextColor(const QColor &color)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->textColor = color;
|
||
|
|
||
|
MATERIAL_DISABLE_THEME_COLORS
|
||
|
setupProperties();
|
||
|
}
|
||
|
|
||
|
QColor QtMaterialCheckable::textColor() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
if (d->useThemeColors || !d->textColor.isValid()) {
|
||
|
return QtMaterialStyle::instance().themeColor("text");
|
||
|
} else {
|
||
|
return d->textColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setDisabledColor(const QColor &color)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->disabledColor = color;
|
||
|
|
||
|
MATERIAL_DISABLE_THEME_COLORS
|
||
|
setupProperties();
|
||
|
}
|
||
|
|
||
|
QColor QtMaterialCheckable::disabledColor() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
if (d->useThemeColors || !d->disabledColor.isValid()) {
|
||
|
return QtMaterialStyle::instance().themeColor("accent3");
|
||
|
} else {
|
||
|
return d->disabledColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setCheckedIcon(const QIcon &icon)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->checkedIcon->setIcon(icon);
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
QIcon QtMaterialCheckable::checkedIcon() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
return d->checkedIcon->icon();
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setUncheckedIcon(const QIcon &icon)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->uncheckedIcon->setIcon(icon);
|
||
|
update();
|
||
|
}
|
||
|
|
||
|
QIcon QtMaterialCheckable::uncheckedIcon() const
|
||
|
{
|
||
|
Q_D(const QtMaterialCheckable);
|
||
|
|
||
|
return d->uncheckedIcon->icon();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \reimp
|
||
|
*/
|
||
|
QSize QtMaterialCheckable::sizeHint() const
|
||
|
{
|
||
|
if (text().isEmpty()) {
|
||
|
return QSize(40, 40);
|
||
|
}
|
||
|
return QSize(fontMetrics().size(Qt::TextShowMnemonic, text()).width()+52, 40);
|
||
|
}
|
||
|
|
||
|
QtMaterialCheckable::QtMaterialCheckable(QtMaterialCheckablePrivate &d, QWidget *parent)
|
||
|
: QAbstractButton(parent),
|
||
|
d_ptr(&d)
|
||
|
{
|
||
|
d_func()->init();
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \reimp
|
||
|
*/
|
||
|
bool QtMaterialCheckable::event(QEvent *event)
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
switch (event->type())
|
||
|
{
|
||
|
case QEvent::Resize:
|
||
|
case QEvent::Move:
|
||
|
d->checkedIcon->setGeometry(rect());
|
||
|
d->uncheckedIcon->setGeometry(rect());
|
||
|
d->rippleOverlay->setGeometry(geometry().adjusted(-8, -8, 8, 8));
|
||
|
break;
|
||
|
case QEvent::ParentChange:
|
||
|
QWidget *widget;
|
||
|
if ((widget = parentWidget())) {
|
||
|
d->rippleOverlay->setParent(widget);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return QAbstractButton::event(event);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \reimp
|
||
|
*/
|
||
|
bool QtMaterialCheckable::eventFilter(QObject *obj, QEvent *event)
|
||
|
{
|
||
|
if (QEvent::Resize == event->type())
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->rippleOverlay->setGeometry(geometry().adjusted(-8, -8, 8, 8));
|
||
|
}
|
||
|
return QAbstractButton::eventFilter(obj, event);
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \reimp
|
||
|
*/
|
||
|
void QtMaterialCheckable::mousePressEvent(QMouseEvent *event)
|
||
|
{
|
||
|
Q_UNUSED(event)
|
||
|
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
if (!isEnabled()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QtMaterialRipple *ripple;
|
||
|
if (QtMaterialCheckable::LabelPositionLeft == d->labelPosition) {
|
||
|
ripple = new QtMaterialRipple(QPoint(width()-14, 28));
|
||
|
} else {
|
||
|
ripple = new QtMaterialRipple(QPoint(28, 28));
|
||
|
}
|
||
|
ripple->setRadiusEndValue(22);
|
||
|
ripple->setColor(isChecked() ? checkedColor() : uncheckedColor());
|
||
|
if (isChecked()) {
|
||
|
ripple->setOpacityStartValue(1);
|
||
|
}
|
||
|
d->rippleOverlay->addRipple(ripple);
|
||
|
|
||
|
setChecked(!isChecked());
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* \reimp
|
||
|
*/
|
||
|
void QtMaterialCheckable::paintEvent(QPaintEvent *event)
|
||
|
{
|
||
|
Q_UNUSED(event)
|
||
|
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
QPainter painter(this);
|
||
|
|
||
|
QPen pen;
|
||
|
pen.setColor(isEnabled() ? textColor() : disabledColor());
|
||
|
painter.setPen(pen);
|
||
|
|
||
|
if (QtMaterialCheckable::LabelPositionLeft == d->labelPosition) {
|
||
|
painter.drawText(4, 25, text());
|
||
|
} else {
|
||
|
painter.drawText(48, 25, text());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void QtMaterialCheckable::setupProperties()
|
||
|
{
|
||
|
Q_D(QtMaterialCheckable);
|
||
|
|
||
|
d->checkedState->assignProperty(d->checkedIcon, "color", checkedColor());
|
||
|
d->checkedState->assignProperty(d->uncheckedIcon, "color", checkedColor());
|
||
|
d->uncheckedState->assignProperty(d->uncheckedIcon, "color", uncheckedColor());
|
||
|
d->disabledUncheckedState->assignProperty(d->uncheckedIcon, "color", disabledColor());
|
||
|
d->disabledCheckedState->assignProperty(d->checkedIcon, "color", disabledColor());
|
||
|
|
||
|
if (isEnabled()) {
|
||
|
if (isChecked()) {
|
||
|
d->checkedIcon->setColor(checkedColor());
|
||
|
} else {
|
||
|
d->uncheckedIcon->setColor(uncheckedColor());
|
||
|
}
|
||
|
} else {
|
||
|
d->checkedIcon->setColor(disabledColor());
|
||
|
d->uncheckedIcon->setColor(disabledColor());
|
||
|
}
|
||
|
|
||
|
update();
|
||
|
}
|