qtmaterialcheckable.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. #include "lib/qtmaterialcheckable.h"
  2. #include "lib/qtmaterialcheckable_p.h"
  3. #include <QPainter>
  4. #include <QEvent>
  5. #include <QStateMachine>
  6. #include <QSignalTransition>
  7. #include <QEventTransition>
  8. #include <QColor>
  9. #include <QCoreApplication>
  10. #include "lib/qtmaterialrippleoverlay.h"
  11. #include "lib/qtmaterialripple.h"
  12. #include "lib/qtmaterialstyle.h"
  13. #include "lib/qtmaterialcheckable_internal.h"
  14. /*!
  15. * \class QtMaterialCheckablePrivate
  16. * \internal
  17. */
  18. QtMaterialCheckablePrivate::QtMaterialCheckablePrivate(QtMaterialCheckable *q)
  19. : q_ptr(q)
  20. {
  21. }
  22. QtMaterialCheckablePrivate::~QtMaterialCheckablePrivate()
  23. {
  24. }
  25. void QtMaterialCheckablePrivate::init()
  26. {
  27. Q_Q(QtMaterialCheckable);
  28. rippleOverlay = new QtMaterialRippleOverlay;
  29. checkedIcon = new QtMaterialCheckableIcon(QIcon(":/icons/icons/toggle/svg/production/ic_check_box_24px.svg"), q);
  30. uncheckedIcon = new QtMaterialCheckableIcon(QIcon(":/icons/icons/toggle/svg/production/ic_check_box_outline_blank_24px.svg"), q);
  31. stateMachine = new QStateMachine(q);
  32. uncheckedState = new QState;
  33. checkedState = new QState;
  34. disabledUncheckedState = new QState;
  35. disabledCheckedState = new QState;
  36. uncheckedTransition = new QSignalTransition(q, SIGNAL(toggled(bool)));
  37. checkedTransition = new QSignalTransition(q, SIGNAL(toggled(bool)));
  38. labelPosition = QtMaterialCheckable::LabelPositionRight;
  39. useThemeColors = true;
  40. rippleOverlay->setParent(q->parentWidget());
  41. rippleOverlay->installEventFilter(q);
  42. q->setCheckable(true);
  43. q->setStyle(&QtMaterialStyle::instance());
  44. q->setFont(QFont("Roboto", 11, QFont::Normal));
  45. stateMachine->addState(uncheckedState);
  46. stateMachine->addState(checkedState);
  47. stateMachine->addState(disabledUncheckedState);
  48. stateMachine->addState(disabledCheckedState);
  49. stateMachine->setInitialState(uncheckedState);
  50. // Transition to checked
  51. uncheckedTransition->setTargetState(checkedState);
  52. uncheckedState->addTransition(uncheckedTransition);
  53. // Transition to unchecked
  54. checkedTransition->setTargetState(uncheckedState);
  55. checkedState->addTransition(checkedTransition);
  56. QAbstractTransition *transition;
  57. // Transitions enabled <==> disabled
  58. transition = new QEventTransition(q, QEvent::EnabledChange);
  59. transition->setTargetState(disabledUncheckedState);
  60. uncheckedState->addTransition(transition);
  61. transition = new QEventTransition(q, QEvent::EnabledChange);
  62. transition->setTargetState(uncheckedState);
  63. disabledUncheckedState->addTransition(transition);
  64. transition = new QEventTransition(q, QEvent::EnabledChange);
  65. transition->setTargetState(disabledCheckedState);
  66. checkedState->addTransition(transition);
  67. transition = new QEventTransition(q, QEvent::EnabledChange);
  68. transition->setTargetState(checkedState);
  69. disabledCheckedState->addTransition(transition);
  70. transition = new QSignalTransition(q, SIGNAL(toggled(bool)));
  71. transition->setTargetState(disabledCheckedState);
  72. disabledUncheckedState->addTransition(transition);
  73. transition = new QSignalTransition(q, SIGNAL(toggled(bool)));
  74. transition->setTargetState(disabledUncheckedState);
  75. disabledCheckedState->addTransition(transition);
  76. //
  77. checkedState->assignProperty(checkedIcon, "opacity", 1);
  78. checkedState->assignProperty(uncheckedIcon, "opacity", 0);
  79. uncheckedState->assignProperty(checkedIcon, "opacity", 0);
  80. uncheckedState->assignProperty(uncheckedIcon, "opacity", 1);
  81. disabledCheckedState->assignProperty(checkedIcon, "opacity", 1);
  82. disabledCheckedState->assignProperty(uncheckedIcon, "opacity", 0);
  83. disabledUncheckedState->assignProperty(checkedIcon, "opacity", 0);
  84. disabledUncheckedState->assignProperty(uncheckedIcon, "opacity", 1);
  85. checkedState->assignProperty(checkedIcon, "color", q->checkedColor());
  86. checkedState->assignProperty(uncheckedIcon, "color", q->checkedColor());
  87. uncheckedState->assignProperty(uncheckedIcon, "color", q->uncheckedColor());
  88. uncheckedState->assignProperty(uncheckedIcon, "color", q->uncheckedColor());
  89. disabledUncheckedState->assignProperty(uncheckedIcon, "color", q->disabledColor());
  90. disabledCheckedState->assignProperty(checkedIcon, "color", q->disabledColor());
  91. stateMachine->start();
  92. QCoreApplication::processEvents();
  93. }
  94. /*!
  95. * \class QtMaterialCheckable
  96. */
  97. QtMaterialCheckable::QtMaterialCheckable(QWidget *parent)
  98. : QAbstractButton(parent),
  99. d_ptr(new QtMaterialCheckablePrivate(this))
  100. {
  101. d_func()->init();
  102. }
  103. QtMaterialCheckable::~QtMaterialCheckable()
  104. {
  105. }
  106. void QtMaterialCheckable::setLabelPosition(LabelPosition placement)
  107. {
  108. Q_D(QtMaterialCheckable);
  109. d->labelPosition = placement;
  110. update();
  111. }
  112. QtMaterialCheckable::LabelPosition QtMaterialCheckable::labelPosition() const
  113. {
  114. Q_D(const QtMaterialCheckable);
  115. return d->labelPosition;
  116. }
  117. void QtMaterialCheckable::setUseThemeColors(bool value)
  118. {
  119. Q_D(QtMaterialCheckable);
  120. if (d->useThemeColors == value) {
  121. return;
  122. }
  123. d->useThemeColors = value;
  124. setupProperties();
  125. }
  126. bool QtMaterialCheckable::useThemeColors() const
  127. {
  128. Q_D(const QtMaterialCheckable);
  129. return d->useThemeColors;
  130. }
  131. void QtMaterialCheckable::setCheckedColor(const QColor &color)
  132. {
  133. Q_D(QtMaterialCheckable);
  134. d->checkedColor = color;
  135. MATERIAL_DISABLE_THEME_COLORS
  136. setupProperties();
  137. }
  138. QColor QtMaterialCheckable::checkedColor() const
  139. {
  140. Q_D(const QtMaterialCheckable);
  141. if (d->useThemeColors || !d->checkedColor.isValid()) {
  142. return QtMaterialStyle::instance().themeColor("primary1");
  143. } else {
  144. return d->checkedColor;
  145. }
  146. }
  147. void QtMaterialCheckable::setUncheckedColor(const QColor &color)
  148. {
  149. Q_D(QtMaterialCheckable);
  150. d->uncheckedColor = color;
  151. MATERIAL_DISABLE_THEME_COLORS
  152. setupProperties();
  153. }
  154. QColor QtMaterialCheckable::uncheckedColor() const
  155. {
  156. Q_D(const QtMaterialCheckable);
  157. if (d->useThemeColors || !d->uncheckedColor.isValid()) {
  158. return QtMaterialStyle::instance().themeColor("text");
  159. } else {
  160. return d->uncheckedColor;
  161. }
  162. }
  163. void QtMaterialCheckable::setTextColor(const QColor &color)
  164. {
  165. Q_D(QtMaterialCheckable);
  166. d->textColor = color;
  167. MATERIAL_DISABLE_THEME_COLORS
  168. setupProperties();
  169. }
  170. QColor QtMaterialCheckable::textColor() const
  171. {
  172. Q_D(const QtMaterialCheckable);
  173. if (d->useThemeColors || !d->textColor.isValid()) {
  174. return QtMaterialStyle::instance().themeColor("text");
  175. } else {
  176. return d->textColor;
  177. }
  178. }
  179. void QtMaterialCheckable::setDisabledColor(const QColor &color)
  180. {
  181. Q_D(QtMaterialCheckable);
  182. d->disabledColor = color;
  183. MATERIAL_DISABLE_THEME_COLORS
  184. setupProperties();
  185. }
  186. QColor QtMaterialCheckable::disabledColor() const
  187. {
  188. Q_D(const QtMaterialCheckable);
  189. if (d->useThemeColors || !d->disabledColor.isValid()) {
  190. return QtMaterialStyle::instance().themeColor("accent3");
  191. } else {
  192. return d->disabledColor;
  193. }
  194. }
  195. void QtMaterialCheckable::setCheckedIcon(const QIcon &icon)
  196. {
  197. Q_D(QtMaterialCheckable);
  198. d->checkedIcon->setIcon(icon);
  199. update();
  200. }
  201. QIcon QtMaterialCheckable::checkedIcon() const
  202. {
  203. Q_D(const QtMaterialCheckable);
  204. return d->checkedIcon->icon();
  205. }
  206. void QtMaterialCheckable::setUncheckedIcon(const QIcon &icon)
  207. {
  208. Q_D(QtMaterialCheckable);
  209. d->uncheckedIcon->setIcon(icon);
  210. update();
  211. }
  212. QIcon QtMaterialCheckable::uncheckedIcon() const
  213. {
  214. Q_D(const QtMaterialCheckable);
  215. return d->uncheckedIcon->icon();
  216. }
  217. /*!
  218. * \reimp
  219. */
  220. QSize QtMaterialCheckable::sizeHint() const
  221. {
  222. if (text().isEmpty()) {
  223. return QSize(40, 40);
  224. }
  225. return QSize(fontMetrics().size(Qt::TextShowMnemonic, text()).width()+52, 40);
  226. }
  227. QtMaterialCheckable::QtMaterialCheckable(QtMaterialCheckablePrivate &d, QWidget *parent)
  228. : QAbstractButton(parent),
  229. d_ptr(&d)
  230. {
  231. d_func()->init();
  232. }
  233. /*!
  234. * \reimp
  235. */
  236. bool QtMaterialCheckable::event(QEvent *event)
  237. {
  238. Q_D(QtMaterialCheckable);
  239. switch (event->type())
  240. {
  241. case QEvent::Resize:
  242. case QEvent::Move:
  243. d->checkedIcon->setGeometry(rect());
  244. d->uncheckedIcon->setGeometry(rect());
  245. d->rippleOverlay->setGeometry(geometry().adjusted(-8, -8, 8, 8));
  246. break;
  247. case QEvent::ParentChange:
  248. QWidget *widget;
  249. if ((widget = parentWidget())) {
  250. d->rippleOverlay->setParent(widget);
  251. }
  252. break;
  253. default:
  254. break;
  255. }
  256. return QAbstractButton::event(event);
  257. }
  258. /*!
  259. * \reimp
  260. */
  261. bool QtMaterialCheckable::eventFilter(QObject *obj, QEvent *event)
  262. {
  263. if (QEvent::Resize == event->type())
  264. {
  265. Q_D(QtMaterialCheckable);
  266. d->rippleOverlay->setGeometry(geometry().adjusted(-8, -8, 8, 8));
  267. }
  268. return QAbstractButton::eventFilter(obj, event);
  269. }
  270. /*!
  271. * \reimp
  272. */
  273. void QtMaterialCheckable::mousePressEvent(QMouseEvent *event)
  274. {
  275. Q_UNUSED(event)
  276. Q_D(QtMaterialCheckable);
  277. if (!isEnabled()) {
  278. return;
  279. }
  280. QtMaterialRipple *ripple;
  281. if (QtMaterialCheckable::LabelPositionLeft == d->labelPosition) {
  282. ripple = new QtMaterialRipple(QPoint(width()-14, 28));
  283. } else {
  284. ripple = new QtMaterialRipple(QPoint(28, 28));
  285. }
  286. ripple->setRadiusEndValue(22);
  287. ripple->setColor(isChecked() ? checkedColor() : uncheckedColor());
  288. if (isChecked()) {
  289. ripple->setOpacityStartValue(1);
  290. }
  291. d->rippleOverlay->addRipple(ripple);
  292. setChecked(!isChecked());
  293. }
  294. /*!
  295. * \reimp
  296. */
  297. void QtMaterialCheckable::paintEvent(QPaintEvent *event)
  298. {
  299. Q_UNUSED(event)
  300. Q_D(QtMaterialCheckable);
  301. QPainter painter(this);
  302. QPen pen;
  303. pen.setColor(isEnabled() ? textColor() : disabledColor());
  304. painter.setPen(pen);
  305. if (QtMaterialCheckable::LabelPositionLeft == d->labelPosition) {
  306. painter.drawText(4, 25, text());
  307. } else {
  308. painter.drawText(48, 25, text());
  309. }
  310. }
  311. void QtMaterialCheckable::setupProperties()
  312. {
  313. Q_D(QtMaterialCheckable);
  314. d->checkedState->assignProperty(d->checkedIcon, "color", checkedColor());
  315. d->checkedState->assignProperty(d->uncheckedIcon, "color", checkedColor());
  316. d->uncheckedState->assignProperty(d->uncheckedIcon, "color", uncheckedColor());
  317. d->disabledUncheckedState->assignProperty(d->uncheckedIcon, "color", disabledColor());
  318. d->disabledCheckedState->assignProperty(d->checkedIcon, "color", disabledColor());
  319. if (isEnabled()) {
  320. if (isChecked()) {
  321. d->checkedIcon->setColor(checkedColor());
  322. } else {
  323. d->uncheckedIcon->setColor(uncheckedColor());
  324. }
  325. } else {
  326. d->checkedIcon->setColor(disabledColor());
  327. d->uncheckedIcon->setColor(disabledColor());
  328. }
  329. update();
  330. }