qtmaterialslider.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. #include "qtmaterialslider.h"
  2. #include "qtmaterialslider_p.h"
  3. #include <QtWidgets/QApplication>
  4. #include <QMouseEvent>
  5. #include "qtmaterialslider_internal.h"
  6. #include "lib/qtmaterialstyle.h"
  7. #include "lib/qtmaterialstatetransitionevent.h"
  8. /*!
  9. * \class QtMaterialSliderPrivate
  10. * \internal
  11. */
  12. QtMaterialSliderPrivate::QtMaterialSliderPrivate(QtMaterialSlider *q)
  13. : q_ptr(q)
  14. {
  15. }
  16. QtMaterialSliderPrivate::~QtMaterialSliderPrivate()
  17. {
  18. }
  19. void QtMaterialSliderPrivate::init()
  20. {
  21. Q_Q(QtMaterialSlider);
  22. thumb = new QtMaterialSliderThumb(q);
  23. track = new QtMaterialSliderTrack(thumb, q);
  24. stateMachine = new QtMaterialSliderStateMachine(q, thumb, track);
  25. stepTo = 0;
  26. oldValue = q->value();
  27. trackWidth = 2;
  28. hoverTrack = false;
  29. hoverThumb = false;
  30. hover = false;
  31. step = false;
  32. pageStepMode = true;
  33. useThemeColors = true;
  34. q->setMouseTracking(true);
  35. q->setFocusPolicy(Qt::StrongFocus);
  36. q->setPageStep(1);
  37. QSizePolicy sp(QSizePolicy::Expanding,
  38. QSizePolicy::Fixed);
  39. if (q->orientation() == Qt::Vertical) {
  40. sp.transpose();
  41. }
  42. q->setSizePolicy(sp);
  43. q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
  44. stateMachine->start();
  45. QCoreApplication::processEvents();
  46. }
  47. QRectF QtMaterialSliderPrivate::trackBoundingRect() const
  48. {
  49. Q_Q(const QtMaterialSlider);
  50. qreal hw = static_cast<qreal>(trackWidth)/2;
  51. return Qt::Horizontal == q->orientation()
  52. ? QRectF(QT_MATERIAL_SLIDER_MARGIN, q->height()/2 - hw,
  53. q->width() - QT_MATERIAL_SLIDER_MARGIN*2, hw*2)
  54. : QRectF(q->width()/2 - hw, QT_MATERIAL_SLIDER_MARGIN, hw*2,
  55. q->height() - QT_MATERIAL_SLIDER_MARGIN*2);
  56. }
  57. QRectF QtMaterialSliderPrivate::thumbBoundingRect() const
  58. {
  59. Q_Q(const QtMaterialSlider);
  60. return Qt::Horizontal == q->orientation()
  61. ? QRectF(thumb->offset(), q->height()/2 - QT_MATERIAL_SLIDER_MARGIN,
  62. QT_MATERIAL_SLIDER_MARGIN*2, QT_MATERIAL_SLIDER_MARGIN*2)
  63. : QRectF(q->width()/2 - QT_MATERIAL_SLIDER_MARGIN, thumb->offset(),
  64. QT_MATERIAL_SLIDER_MARGIN*2, QT_MATERIAL_SLIDER_MARGIN*2);
  65. }
  66. int QtMaterialSliderPrivate::valueFromPosition(const QPoint &pos) const
  67. {
  68. Q_Q(const QtMaterialSlider);
  69. const int position = Qt::Horizontal == q->orientation() ? pos.x() : pos.y();
  70. const int span = Qt::Horizontal == q->orientation()
  71. ? q->width() - QT_MATERIAL_SLIDER_MARGIN*2
  72. : q->height() - QT_MATERIAL_SLIDER_MARGIN*2;
  73. return QtMaterialStyle::sliderValueFromPosition(
  74. q->minimum(),
  75. q->maximum(),
  76. position - QT_MATERIAL_SLIDER_MARGIN,
  77. span,
  78. q->invertedAppearance());
  79. }
  80. void QtMaterialSliderPrivate::setHovered(bool status)
  81. {
  82. Q_Q(QtMaterialSlider);
  83. if (hover == status) {
  84. return;
  85. }
  86. hover = status;
  87. if (!q->hasFocus()) {
  88. if (status) {
  89. stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderNoFocusMouseEnter));
  90. } else {
  91. stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderNoFocusMouseLeave));
  92. }
  93. }
  94. q->update();
  95. }
  96. /*!
  97. * \class QtMaterialSlider
  98. */
  99. QtMaterialSlider::QtMaterialSlider(QWidget *parent)
  100. : QAbstractSlider(parent),
  101. d_ptr(new QtMaterialSliderPrivate(this))
  102. {
  103. d_func()->init();
  104. }
  105. QtMaterialSlider::~QtMaterialSlider()
  106. {
  107. }
  108. void QtMaterialSlider::setUseThemeColors(bool value)
  109. {
  110. Q_D(QtMaterialSlider);
  111. if (d->useThemeColors == value) {
  112. return;
  113. }
  114. d->useThemeColors = value;
  115. d->stateMachine->setupProperties();
  116. }
  117. bool QtMaterialSlider::useThemeColors() const
  118. {
  119. Q_D(const QtMaterialSlider);
  120. return d->useThemeColors;
  121. }
  122. void QtMaterialSlider::setThumbColor(const QColor &color)
  123. {
  124. Q_D(QtMaterialSlider);
  125. d->thumbColor = color;
  126. MATERIAL_DISABLE_THEME_COLORS
  127. d->stateMachine->setupProperties();
  128. update();
  129. }
  130. QColor QtMaterialSlider::thumbColor() const
  131. {
  132. Q_D(const QtMaterialSlider);
  133. if (d->useThemeColors || !d->thumbColor.isValid()) {
  134. return QtMaterialStyle::instance().themeColor("primary1");
  135. } else {
  136. return d->thumbColor;
  137. }
  138. }
  139. void QtMaterialSlider::setTrackColor(const QColor &color)
  140. {
  141. Q_D(QtMaterialSlider);
  142. d->trackColor = color;
  143. MATERIAL_DISABLE_THEME_COLORS
  144. d->stateMachine->setupProperties();
  145. update();
  146. }
  147. QColor QtMaterialSlider::trackColor() const
  148. {
  149. Q_D(const QtMaterialSlider);
  150. if (d->useThemeColors || !d->trackColor.isValid()) {
  151. return QtMaterialStyle::instance().themeColor("accent3");
  152. } else {
  153. return d->trackColor;
  154. }
  155. }
  156. void QtMaterialSlider::setDisabledColor(const QColor &color)
  157. {
  158. Q_D(QtMaterialSlider);
  159. d->disabledColor = color;
  160. MATERIAL_DISABLE_THEME_COLORS
  161. d->stateMachine->setupProperties();
  162. update();
  163. }
  164. QColor QtMaterialSlider::disabledColor() const
  165. {
  166. Q_D(const QtMaterialSlider);
  167. if (d->useThemeColors || !d->disabledColor.isValid()) {
  168. return QtMaterialStyle::instance().themeColor("disabled");
  169. } else {
  170. return d->disabledColor;
  171. }
  172. }
  173. void QtMaterialSlider::setPageStepMode(bool pageStep)
  174. {
  175. Q_D(QtMaterialSlider);
  176. d->pageStepMode = pageStep;
  177. }
  178. bool QtMaterialSlider::pageStepMode() const
  179. {
  180. Q_D(const QtMaterialSlider);
  181. return d->pageStepMode;
  182. }
  183. /*!
  184. * \remip
  185. */
  186. QSize QtMaterialSlider::minimumSizeHint() const
  187. {
  188. return Qt::Horizontal == orientation()
  189. ? QSize(130, 34)
  190. : QSize(34, 130);
  191. }
  192. void QtMaterialSlider::setInvertedAppearance(bool value)
  193. {
  194. QAbstractSlider::setInvertedAppearance(value);
  195. updateThumbOffset();
  196. }
  197. /*!
  198. * \remip
  199. */
  200. void QtMaterialSlider::sliderChange(SliderChange change)
  201. {
  202. Q_D(QtMaterialSlider);
  203. if (SliderOrientationChange == change)
  204. {
  205. QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed);
  206. if (orientation() == Qt::Vertical) {
  207. sp.transpose();
  208. }
  209. setSizePolicy(sp);
  210. }
  211. else if (SliderValueChange == change)
  212. {
  213. if (minimum() == value()) {
  214. triggerAction(SliderToMinimum);
  215. d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedToMinimum));
  216. } else if (maximum() == value()) {
  217. triggerAction(SliderToMaximum);
  218. }
  219. if (minimum() == d->oldValue) {
  220. d->stateMachine->postEvent(new QtMaterialStateTransitionEvent(SliderChangedFromMinimum));
  221. }
  222. d->oldValue = value();
  223. }
  224. updateThumbOffset();
  225. QAbstractSlider::sliderChange(change);
  226. }
  227. /*!
  228. * \remip
  229. */
  230. void QtMaterialSlider::mouseMoveEvent(QMouseEvent *event)
  231. {
  232. Q_D(QtMaterialSlider);
  233. if (isSliderDown())
  234. {
  235. setSliderPosition(d->valueFromPosition(event->pos()));
  236. }
  237. else
  238. {
  239. QRectF track(d->trackBoundingRect().adjusted(-2, -2, 2, 2));
  240. if (track.contains(event->pos()) != d->hoverTrack) {
  241. d->hoverTrack = !d->hoverTrack;
  242. update();
  243. }
  244. QRectF thumb(0, 0, 16, 16);
  245. thumb.moveCenter(d->thumbBoundingRect().center());
  246. if (thumb.contains(event->pos()) != d->hoverThumb) {
  247. d->hoverThumb = !d->hoverThumb;
  248. update();
  249. }
  250. d->setHovered(d->hoverTrack || d->hoverThumb);
  251. }
  252. QAbstractSlider::mouseMoveEvent(event);
  253. }
  254. /*!
  255. * \remip
  256. */
  257. void QtMaterialSlider::mousePressEvent(QMouseEvent *event)
  258. {
  259. Q_D(QtMaterialSlider);
  260. const QPoint pos = event->pos();
  261. QRectF thumb(0, 0, 16, 16);
  262. thumb.moveCenter(d->thumbBoundingRect().center());
  263. if (thumb.contains(pos)) {
  264. setSliderDown(true);
  265. return;
  266. }
  267. if (!d->pageStepMode) {
  268. setSliderPosition(d->valueFromPosition(event->pos()));
  269. d->thumb->setHaloSize(0);
  270. setSliderDown(true);
  271. return;
  272. }
  273. d->step = true;
  274. d->stepTo = d->valueFromPosition(pos);
  275. SliderAction action = d->stepTo > sliderPosition()
  276. ? SliderPageStepAdd
  277. : SliderPageStepSub;
  278. triggerAction(action);
  279. setRepeatAction(action, 400, 8);
  280. }
  281. /*!
  282. * \remip
  283. */
  284. void QtMaterialSlider::mouseReleaseEvent(QMouseEvent *event)
  285. {
  286. Q_D(QtMaterialSlider);
  287. if (isSliderDown()) {
  288. setSliderDown(false);
  289. } else if (d->step) {
  290. d->step = false;
  291. setRepeatAction(SliderNoAction, 0);
  292. }
  293. QAbstractSlider::mouseReleaseEvent(event);
  294. }
  295. /*!
  296. * \remip
  297. */
  298. void QtMaterialSlider::leaveEvent(QEvent *event)
  299. {
  300. Q_D(QtMaterialSlider);
  301. if (d->hoverTrack) {
  302. d->hoverTrack = false;
  303. update();
  304. }
  305. if (d->hoverThumb) {
  306. d->hoverThumb = false;
  307. update();
  308. }
  309. d->setHovered(false);
  310. QAbstractSlider::leaveEvent(event);
  311. }
  312. void QtMaterialSlider::updateThumbOffset()
  313. {
  314. Q_D(QtMaterialSlider);
  315. const int offset = QtMaterialStyle::sliderPositionFromValue(
  316. minimum(),
  317. maximum(),
  318. sliderPosition(),
  319. Qt::Horizontal == orientation()
  320. ? width() - QT_MATERIAL_SLIDER_MARGIN*2
  321. : height() - QT_MATERIAL_SLIDER_MARGIN*2,
  322. invertedAppearance());
  323. d->thumb->setOffset(offset);
  324. }