ArchitectureColoredPainting/qt-material-widgets/components/qtmaterialflatbutton_intern...

233 lines
8.3 KiB
C++

#include "qtmaterialflatbutton_internal.h"
#include <QEventTransition>
#include <QPropertyAnimation>
#include <QFocusEvent>
#include <QSequentialAnimationGroup>
#include "qtmaterialflatbutton.h"
#include "lib/qtmaterialstatetransition.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);
QtMaterialStateTransition *transition;
QPropertyAnimation *animation;
transition = new QtMaterialStateTransition(FlatButtonCheckedTransition);
transition->setTargetState(m_checkedState);
m_uncheckedState->addTransition(transition);
animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
animation->setDuration(200);
transition->addAnimation(animation);
transition = new QtMaterialStateTransition(FlatButtonUncheckedTransition);
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);
transition = new QtMaterialStateTransition(FlatButtonPressedTransition);
transition->setTargetState(m_pressedState);
m_hoveredState->addTransition(transition);
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 progress)
{
m_checkedOverlayProgress = progress;
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) {
postEvent(new QtMaterialStateTransitionEvent(FlatButtonCheckedTransition));
} else {
postEvent(new QtMaterialStateTransitionEvent(FlatButtonUncheckedTransition));
}
}
}
bool QtMaterialFlatButtonStateMachine::eventFilter(QObject *watched,
QEvent *event)
{
if (QEvent::FocusIn == event->type()) {
QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) {
postEvent(new QtMaterialStateTransitionEvent(FlatButtonPressedTransition));
return true;
}
}
return QStateMachine::eventFilter(watched, event);
}
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);
}