#include "qtmaterialslider_internal.h" #include #include #include #include #include #include #include "qtmaterialslider.h" #include "lib/qtmaterialstyle.h" #include "lib/qtmaterialstatetransition.h" /*! * \class QtMaterialSliderStateMachine * \internal */ QtMaterialSliderStateMachine::QtMaterialSliderStateMachine( QtMaterialSlider *slider, QtMaterialSliderThumb *thumb, QtMaterialSliderTrack *track) : QStateMachine(slider), m_slider(slider), m_thumb(thumb), m_track(track), m_topState(new QState(QState::ParallelStates)), m_fstState(new QState(m_topState)), m_sndState(new QState(m_topState)), m_inactiveState(new QState(m_fstState)), m_focusState(new QState(m_fstState)), m_slidingState(new QState(m_fstState)), m_pulseOutState(new QState(m_focusState)), m_pulseInState(new QState(m_focusState)), m_minState(new QState(m_sndState)), m_normalState(new QState(m_sndState)) { addState(m_topState); setInitialState(m_topState); m_fstState->setInitialState(m_inactiveState); m_focusState->setInitialState(m_pulseOutState); m_inactiveState->assignProperty(thumb, "haloSize", 0); m_slidingState->assignProperty(thumb, "haloSize", 0); m_pulseOutState->assignProperty(thumb, "haloSize", 35); m_pulseInState->assignProperty(thumb, "haloSize", 28); m_inactiveState->assignProperty(thumb, "diameter", 11); m_focusState->assignProperty(thumb, "diameter", 11); m_slidingState->assignProperty(thumb, "diameter", 17); QAbstractTransition *transition; QtMaterialStateTransition *customTransition; QPropertyAnimation *animation; // Show halo on mouse enter customTransition = new QtMaterialStateTransition(SliderNoFocusMouseEnter); customTransition->setTargetState(m_focusState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); customTransition->addAnimation(animation); customTransition->addAnimation(new QPropertyAnimation(track, "fillColor", this)); m_inactiveState->addTransition(customTransition); // Show halo on focus in transition = new QEventTransition(slider, QEvent::FocusIn); transition->setTargetState(m_focusState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); transition->addAnimation(animation); transition->addAnimation(new QPropertyAnimation(track, "fillColor", this)); m_inactiveState->addTransition(transition); // Hide halo on focus out transition = new QEventTransition(slider, QEvent::FocusOut); transition->setTargetState(m_inactiveState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); transition->addAnimation(animation); transition->addAnimation(new QPropertyAnimation(track, "fillColor", this)); m_focusState->addTransition(transition); // Hide halo on mouse leave, except if widget has focus customTransition = new QtMaterialStateTransition(SliderNoFocusMouseLeave); customTransition->setTargetState(m_inactiveState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); customTransition->addAnimation(animation); customTransition->addAnimation(new QPropertyAnimation(track, "fillColor", this)); m_focusState->addTransition(customTransition); // Pulse in transition = new QSignalTransition(m_pulseOutState, SIGNAL(propertiesAssigned())); transition->setTargetState(m_pulseInState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); animation->setDuration(1000); transition->addAnimation(animation); m_pulseOutState->addTransition(transition); // Pulse out transition = new QSignalTransition(m_pulseInState, SIGNAL(propertiesAssigned())); transition->setTargetState(m_pulseOutState); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); animation->setDuration(1000); transition->addAnimation(animation); m_pulseInState->addTransition(transition); // Slider pressed transition = new QSignalTransition(slider, SIGNAL(sliderPressed())); transition->setTargetState(m_slidingState); animation = new QPropertyAnimation(thumb, "diameter", this); animation->setDuration(70); transition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); transition->addAnimation(animation); m_focusState->addTransition(transition); // Slider released transition = new QSignalTransition(slider, SIGNAL(sliderReleased())); transition->setTargetState(m_focusState); animation = new QPropertyAnimation(thumb, "diameter", this); animation->setDuration(70); transition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "haloSize", this); animation->setEasingCurve(QEasingCurve::InOutSine); transition->addAnimation(animation); m_slidingState->addTransition(transition); // Min. value transitions m_minState->assignProperty(thumb, "borderWidth", 2); m_normalState->assignProperty(thumb, "borderWidth", 0); m_sndState->setInitialState(m_minState); customTransition = new QtMaterialStateTransition(SliderChangedFromMinimum); customTransition->setTargetState(m_normalState); animation = new QPropertyAnimation(thumb, "fillColor", this); animation->setDuration(200); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "haloColor", this); animation->setDuration(300); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "borderColor", this); animation->setDuration(200); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "borderWidth", this); animation->setDuration(200); customTransition->addAnimation(animation); m_minState->addTransition(customTransition); customTransition = new QtMaterialStateTransition(SliderChangedToMinimum); customTransition->setTargetState(m_minState); animation = new QPropertyAnimation(thumb, "fillColor", this); animation->setDuration(200); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "haloColor", this); animation->setDuration(300); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "borderColor", this); animation->setDuration(200); customTransition->addAnimation(animation); animation = new QPropertyAnimation(thumb, "borderWidth", this); animation->setDuration(200); customTransition->addAnimation(animation); m_normalState->addTransition(customTransition); setupProperties(); } QtMaterialSliderStateMachine::~QtMaterialSliderStateMachine() { } void QtMaterialSliderStateMachine::setupProperties() { QColor trackColor = m_slider->trackColor(); QColor thumbColor = m_slider->thumbColor(); m_inactiveState->assignProperty(m_track, "fillColor", trackColor.lighter(130)); m_slidingState->assignProperty(m_track, "fillColor", trackColor); m_focusState->assignProperty(m_track, "fillColor", trackColor); QColor holeColor = m_slider->palette().color(QPalette::Base); if (m_slider->parentWidget()) { holeColor = m_slider->parentWidget()->palette().color(m_slider->backgroundRole()); } m_minState->assignProperty(m_thumb, "fillColor", holeColor); m_minState->assignProperty(m_thumb, "haloColor", trackColor); m_minState->assignProperty(m_thumb, "borderColor", trackColor); m_normalState->assignProperty(m_thumb, "fillColor", thumbColor); m_normalState->assignProperty(m_thumb, "haloColor", thumbColor); m_normalState->assignProperty(m_thumb, "borderColor", thumbColor); m_slider->update(); } /*! * \class QtMaterialSliderThumb * \internal */ QtMaterialSliderThumb::QtMaterialSliderThumb(QtMaterialSlider *slider) : QtMaterialOverlayWidget(slider->parentWidget()), m_slider(slider), m_diameter(11), m_borderWidth(2), m_haloSize(0), m_offset(0) { slider->installEventFilter(this); setAttribute(Qt::WA_TransparentForMouseEvents, true); } QtMaterialSliderThumb::~QtMaterialSliderThumb() { } bool QtMaterialSliderThumb::eventFilter(QObject *obj, QEvent *event) { if (QEvent::ParentChange == event->type()) { setParent(m_slider->parentWidget()); } return QtMaterialOverlayWidget::eventFilter(obj, event); } void QtMaterialSliderThumb::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // Halo QBrush brush; brush.setStyle(Qt::SolidPattern); brush.setColor(m_haloColor); painter.setBrush(brush); painter.setPen(Qt::NoPen); QPointF disp = Qt::Horizontal == m_slider->orientation() ? QPointF(QT_MATERIAL_SLIDER_MARGIN + m_offset, m_slider->height()/2) : QPointF(m_slider->width()/2, QT_MATERIAL_SLIDER_MARGIN + m_offset); QRectF halo((m_slider->pos() - QPointF(m_haloSize, m_haloSize)/2) + disp, QSizeF(m_haloSize, m_haloSize)); painter.setOpacity(0.15); painter.drawEllipse(halo); // Knob const bool isMin = m_slider->value() == m_slider->minimum(); brush.setColor(m_slider->isEnabled() ? m_fillColor : m_slider->disabledColor()); painter.setBrush(!m_slider->isEnabled() && isMin ? Qt::NoBrush : brush); if (m_slider->isEnabled() || isMin) { QPen pen; pen.setColor(m_borderColor); pen.setWidthF((isMin && !m_slider->isEnabled()) ? 1.7 : m_borderWidth); painter.setPen(pen); } else { painter.setPen(Qt::NoPen); } QRectF geometry = Qt::Horizontal == m_slider->orientation() ? QRectF(m_offset, m_slider->height()/2 - QT_MATERIAL_SLIDER_MARGIN, QT_MATERIAL_SLIDER_MARGIN*2, QT_MATERIAL_SLIDER_MARGIN*2).translated(m_slider->pos()) : QRectF(m_slider->width()/2 - QT_MATERIAL_SLIDER_MARGIN, m_offset, QT_MATERIAL_SLIDER_MARGIN*2, QT_MATERIAL_SLIDER_MARGIN*2).translated(m_slider->pos()); qreal s = m_slider->isEnabled() ? m_diameter : 7; QRectF thumb(0, 0, s, s); thumb.moveCenter(geometry.center()); painter.setOpacity(1); painter.drawEllipse(thumb); } /*! * \class QtMaterialSliderTrack * \internal */ QtMaterialSliderTrack::QtMaterialSliderTrack(QtMaterialSliderThumb *thumb, QtMaterialSlider *slider) : QtMaterialOverlayWidget(slider->parentWidget()), m_slider(slider), m_thumb(thumb), m_trackWidth(2) { slider->installEventFilter(this); setAttribute(Qt::WA_TransparentForMouseEvents, true); connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(update())); } QtMaterialSliderTrack::~QtMaterialSliderTrack() { } bool QtMaterialSliderTrack::eventFilter(QObject *obj, QEvent *event) { if (QEvent::ParentChange == event->type()) { setParent(m_slider->parentWidget()); } return QtMaterialOverlayWidget::eventFilter(obj, event); } void QtMaterialSliderTrack::paintEvent(QPaintEvent *event) { Q_UNUSED(event) QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QBrush fg; fg.setStyle(Qt::SolidPattern); fg.setColor(m_slider->isEnabled() ? m_slider->thumbColor() : m_slider->disabledColor()); QBrush bg; bg.setStyle(Qt::SolidPattern); bg.setColor(m_slider->isEnabled() ? m_fillColor : m_slider->disabledColor()); qreal offset = m_thumb->offset(); if (Qt::Horizontal == m_slider->orientation()) { painter.translate(m_slider->x() + QT_MATERIAL_SLIDER_MARGIN, m_slider->y() + m_slider->height()/2 - static_cast(m_trackWidth)/2); } else { painter.translate(m_slider->x() + m_slider->width()/2 - static_cast(m_trackWidth)/2, m_slider->y() + QT_MATERIAL_SLIDER_MARGIN); } QRectF geometry = Qt::Horizontal == m_slider->orientation() ? QRectF(0, 0, m_slider->width() - QT_MATERIAL_SLIDER_MARGIN*2, m_trackWidth) : QRectF(0, 0, m_trackWidth, m_slider->height() - QT_MATERIAL_SLIDER_MARGIN*2); QRectF bgRect; QRectF fgRect; if (Qt::Horizontal == m_slider->orientation()) { fgRect = QRectF(0, 0, offset, m_trackWidth); bgRect = QRectF(offset, 0, m_slider->width(), m_trackWidth).intersected(geometry); } else { fgRect = QRectF(0, 0, m_trackWidth, offset); bgRect = QRectF(0, offset, m_trackWidth, m_slider->height()).intersected(geometry); } if (!m_slider->isEnabled()) { fgRect = fgRect.width() < 9 ? QRectF() : fgRect.adjusted(0, 0, -6, 0); bgRect = bgRect.width() < 9 ? QRectF() : bgRect.adjusted(6, 0, 0, 0); } if (m_slider->invertedAppearance()) { qSwap(bgRect, fgRect); } painter.fillRect(bgRect, bg); painter.fillRect(fgRect, fg); }