qtmaterialflatbutton_internal.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #include "qtmaterialflatbutton_internal.h"
  2. #include <QEventTransition>
  3. #include <QPropertyAnimation>
  4. #include <QFocusEvent>
  5. #include <QSequentialAnimationGroup>
  6. #include "qtmaterialflatbutton.h"
  7. #include "lib/qtmaterialstatetransition.h"
  8. /*!
  9. * \class QtMaterialFlatButtonStateMachine
  10. * \internal
  11. */
  12. QtMaterialFlatButtonStateMachine::QtMaterialFlatButtonStateMachine(QtMaterialFlatButton *parent)
  13. : QStateMachine(parent),
  14. m_button(parent),
  15. m_topLevelState(new QState(QState::ParallelStates)),
  16. m_configState(new QState(m_topLevelState)),
  17. m_checkableState(new QState(m_topLevelState)),
  18. m_checkedState(new QState(m_checkableState)),
  19. m_uncheckedState(new QState(m_checkableState)),
  20. m_neutralState(new QState(m_configState)),
  21. m_neutralFocusedState(new QState(m_configState)),
  22. m_hoveredState(new QState(m_configState)),
  23. m_hoveredFocusedState(new QState(m_configState)),
  24. m_pressedState(new QState(m_configState)),
  25. m_haloAnimation(new QSequentialAnimationGroup(this)),
  26. m_overlayOpacity(0),
  27. m_checkedOverlayProgress(parent->isChecked() ? 1 : 0),
  28. m_haloOpacity(0),
  29. m_haloSize(0.8),
  30. m_haloScaleFactor(1),
  31. m_wasChecked(false)
  32. {
  33. Q_ASSERT(parent);
  34. parent->installEventFilter(this);
  35. m_configState->setInitialState(m_neutralState);
  36. addState(m_topLevelState);
  37. setInitialState(m_topLevelState);
  38. m_checkableState->setInitialState(parent->isChecked() ? m_checkedState
  39. : m_uncheckedState);
  40. QtMaterialStateTransition *transition;
  41. QPropertyAnimation *animation;
  42. transition = new QtMaterialStateTransition(FlatButtonCheckedTransition);
  43. transition->setTargetState(m_checkedState);
  44. m_uncheckedState->addTransition(transition);
  45. animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
  46. animation->setDuration(200);
  47. transition->addAnimation(animation);
  48. transition = new QtMaterialStateTransition(FlatButtonUncheckedTransition);
  49. transition->setTargetState(m_uncheckedState);
  50. m_checkedState->addTransition(transition);
  51. animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
  52. animation->setDuration(200);
  53. transition->addAnimation(animation);
  54. addTransition(m_button, QEvent::FocusIn, m_neutralState, m_neutralFocusedState);
  55. addTransition(m_button, QEvent::FocusOut, m_neutralFocusedState, m_neutralState);
  56. addTransition(m_button, QEvent::Enter, m_neutralState, m_hoveredState);
  57. addTransition(m_button, QEvent::Leave, m_hoveredState, m_neutralState);
  58. addTransition(m_button, QEvent::Enter, m_neutralFocusedState, m_hoveredFocusedState);
  59. addTransition(m_button, QEvent::Leave, m_hoveredFocusedState, m_neutralFocusedState);
  60. addTransition(m_button, QEvent::FocusIn, m_hoveredState, m_hoveredFocusedState);
  61. addTransition(m_button, QEvent::FocusOut, m_hoveredFocusedState, m_hoveredState);
  62. transition = new QtMaterialStateTransition(FlatButtonPressedTransition);
  63. transition->setTargetState(m_pressedState);
  64. m_hoveredState->addTransition(transition);
  65. addTransition(m_button, QEvent::Leave, m_pressedState, m_neutralFocusedState);
  66. addTransition(m_button, QEvent::FocusOut, m_pressedState, m_hoveredState);
  67. m_neutralState->assignProperty(this, "haloSize", 0);
  68. m_neutralFocusedState->assignProperty(this, "haloSize", 0.7);
  69. m_hoveredState->assignProperty(this, "haloSize", 0);
  70. m_pressedState->assignProperty(this, "haloSize", 4);
  71. m_hoveredFocusedState->assignProperty(this, "haloSize", 0.7);
  72. QPropertyAnimation *grow = new QPropertyAnimation(this);
  73. QPropertyAnimation *shrink = new QPropertyAnimation(this);
  74. grow->setTargetObject(this);
  75. grow->setPropertyName("haloScaleFactor");
  76. grow->setStartValue(0.56);
  77. grow->setEndValue(0.63);
  78. grow->setEasingCurve(QEasingCurve::InOutSine);
  79. grow->setDuration(840);
  80. shrink->setTargetObject(this);
  81. shrink->setPropertyName("haloScaleFactor");
  82. shrink->setStartValue(0.63);
  83. shrink->setEndValue(0.56);
  84. shrink->setEasingCurve(QEasingCurve::InOutSine);
  85. shrink->setDuration(840);
  86. m_haloAnimation->addAnimation(grow);
  87. m_haloAnimation->addAnimation(shrink);
  88. m_haloAnimation->setLoopCount(-1);
  89. }
  90. QtMaterialFlatButtonStateMachine::~QtMaterialFlatButtonStateMachine()
  91. {
  92. }
  93. void QtMaterialFlatButtonStateMachine::setOverlayOpacity(qreal opacity)
  94. {
  95. m_overlayOpacity = opacity;
  96. m_button->update();
  97. }
  98. void QtMaterialFlatButtonStateMachine::setCheckedOverlayProgress(qreal progress)
  99. {
  100. m_checkedOverlayProgress = progress;
  101. m_button->update();
  102. }
  103. void QtMaterialFlatButtonStateMachine::setHaloOpacity(qreal opacity)
  104. {
  105. m_haloOpacity = opacity;
  106. m_button->update();
  107. }
  108. void QtMaterialFlatButtonStateMachine::setHaloSize(qreal size)
  109. {
  110. m_haloSize = size;
  111. m_button->update();
  112. }
  113. void QtMaterialFlatButtonStateMachine::setHaloScaleFactor(qreal factor)
  114. {
  115. m_haloScaleFactor = factor;
  116. m_button->update();
  117. }
  118. void QtMaterialFlatButtonStateMachine::startAnimations()
  119. {
  120. m_haloAnimation->start();
  121. start();
  122. }
  123. void QtMaterialFlatButtonStateMachine::setupProperties()
  124. {
  125. QColor overlayColor;
  126. if (Qt::TransparentMode == m_button->backgroundMode()) {
  127. overlayColor = m_button->backgroundColor();
  128. } else {
  129. overlayColor = m_button->foregroundColor();
  130. }
  131. const qreal baseOpacity = m_button->baseOpacity();
  132. m_neutralState->assignProperty(this, "overlayOpacity", 0);
  133. m_neutralState->assignProperty(this, "haloOpacity", 0);
  134. m_neutralFocusedState->assignProperty(this, "overlayOpacity", 0);
  135. m_neutralFocusedState->assignProperty(this, "haloOpacity", baseOpacity);
  136. m_hoveredState->assignProperty(this, "overlayOpacity", baseOpacity);
  137. m_hoveredState->assignProperty(this, "haloOpacity", 0);
  138. m_hoveredFocusedState->assignProperty(this, "overlayOpacity", baseOpacity);
  139. m_hoveredFocusedState->assignProperty(this, "haloOpacity", baseOpacity);
  140. m_pressedState->assignProperty(this, "overlayOpacity", baseOpacity);
  141. m_pressedState->assignProperty(this, "haloOpacity", 0);
  142. m_checkedState->assignProperty(this, "checkedOverlayProgress", 1);
  143. m_uncheckedState->assignProperty(this, "checkedOverlayProgress", 0);
  144. m_button->update();
  145. }
  146. void QtMaterialFlatButtonStateMachine::updateCheckedStatus()
  147. {
  148. const bool checked = m_button->isChecked();
  149. if (m_wasChecked != checked) {
  150. m_wasChecked = checked;
  151. if (checked) {
  152. postEvent(new QtMaterialStateTransitionEvent(FlatButtonCheckedTransition));
  153. } else {
  154. postEvent(new QtMaterialStateTransitionEvent(FlatButtonUncheckedTransition));
  155. }
  156. }
  157. }
  158. bool QtMaterialFlatButtonStateMachine::eventFilter(QObject *watched,
  159. QEvent *event)
  160. {
  161. if (QEvent::FocusIn == event->type()) {
  162. QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
  163. if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) {
  164. postEvent(new QtMaterialStateTransitionEvent(FlatButtonPressedTransition));
  165. return true;
  166. }
  167. }
  168. return QStateMachine::eventFilter(watched, event);
  169. }
  170. void QtMaterialFlatButtonStateMachine::addTransition(QObject *object,
  171. QEvent::Type eventType,
  172. QState *fromState,
  173. QState *toState)
  174. {
  175. addTransition(new QEventTransition(object, eventType), fromState, toState);
  176. }
  177. void QtMaterialFlatButtonStateMachine::addTransition(QAbstractTransition *transition,
  178. QState *fromState,
  179. QState *toState)
  180. {
  181. transition->setTargetState(toState);
  182. QPropertyAnimation *animation;
  183. animation = new QPropertyAnimation(this, "overlayOpacity", this);
  184. animation->setDuration(150);
  185. transition->addAnimation(animation);
  186. animation = new QPropertyAnimation(this, "haloOpacity", this);
  187. animation->setDuration(170);
  188. transition->addAnimation(animation);
  189. animation = new QPropertyAnimation(this, "haloSize", this);
  190. animation->setDuration(350);
  191. animation->setEasingCurve(QEasingCurve::OutCubic);
  192. transition->addAnimation(animation);
  193. fromState->addTransition(transition);
  194. }