qtmaterialfab.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include "qtmaterialfab.h"
  2. #include "qtmaterialfab_p.h"
  3. #include <QtWidgets/QGraphicsDropShadowEffect>
  4. #include <QState>
  5. #include <QEvent>
  6. #include <QPainter>
  7. #include "lib/qtmaterialrippleoverlay.h"
  8. /*!
  9. * \class QtMaterialFloatingActionButtonPrivate
  10. * \internal
  11. */
  12. /*!
  13. * \internal
  14. */
  15. QtMaterialFloatingActionButtonPrivate::QtMaterialFloatingActionButtonPrivate(QtMaterialFloatingActionButton *q)
  16. : QtMaterialRaisedButtonPrivate(q)
  17. {
  18. }
  19. /*!
  20. * \internal
  21. */
  22. QtMaterialFloatingActionButtonPrivate::~QtMaterialFloatingActionButtonPrivate()
  23. {
  24. }
  25. /*!
  26. * \internal
  27. */
  28. void QtMaterialFloatingActionButtonPrivate::init()
  29. {
  30. Q_Q(QtMaterialFloatingActionButton);
  31. corner = Qt::BottomRightCorner;
  32. mini = false;
  33. offsX = 34;
  34. offsY = 36;
  35. q->setRole(Material::Primary);
  36. q->setFixedSize(DefaultDiameter, DefaultDiameter);
  37. q->setGeometry(fabGeometry());
  38. setupProperties();
  39. if (q->parentWidget()) {
  40. q->parentWidget()->installEventFilter(q);
  41. }
  42. q->setFixedRippleRadius(50);
  43. }
  44. /*!
  45. * \internal
  46. */
  47. QRect QtMaterialFloatingActionButtonPrivate::fabGeometry() const
  48. {
  49. Q_Q(const QtMaterialFloatingActionButton);
  50. QWidget *parent = q->parentWidget();
  51. if (!parent) {
  52. return QRect();
  53. }
  54. const int s = mini ? MiniDiameter : DefaultDiameter;
  55. switch (corner)
  56. {
  57. case Qt::TopLeftCorner:
  58. return QRect(offsX, offsY, s, s);
  59. case Qt::TopRightCorner:
  60. return QRect(parent->width()-(offsX+s), offsY, s, s);
  61. case Qt::BottomLeftCorner:
  62. return QRect(offsX, parent->height()-(offsY+s), s, s);
  63. case Qt::BottomRightCorner:
  64. default:
  65. break;
  66. }
  67. return QRect(parent->width()-(offsX+s), parent->height()-(offsY+s), s, s);
  68. }
  69. /*!
  70. * \internal
  71. */
  72. void QtMaterialFloatingActionButtonPrivate::setupProperties()
  73. {
  74. if (mini) {
  75. effect->setColor(QColor(0, 0, 0, 80));
  76. normalState->assignProperty(effect, "offset", QPointF(0, 3));
  77. normalState->assignProperty(effect, "blurRadius", 13);
  78. pressedState->assignProperty(effect, "offset", QPointF(0, 7));
  79. pressedState->assignProperty(effect, "blurRadius", 20);
  80. } else {
  81. effect->setColor(QColor(0, 0, 0, 105));
  82. normalState->assignProperty(effect, "offset", QPointF(0, 6));
  83. normalState->assignProperty(effect, "blurRadius", 16);
  84. pressedState->assignProperty(effect, "offset", QPointF(0, 11));
  85. pressedState->assignProperty(effect, "blurRadius", 28);
  86. }
  87. }
  88. /*!
  89. * \class QtMaterialFloatingActionButton
  90. */
  91. QtMaterialFloatingActionButton::QtMaterialFloatingActionButton(const QIcon &icon, QWidget *parent)
  92. : QtMaterialRaisedButton(*new QtMaterialFloatingActionButtonPrivate(this), parent)
  93. {
  94. d_func()->init();
  95. setIcon(icon);
  96. }
  97. QtMaterialFloatingActionButton::~QtMaterialFloatingActionButton()
  98. {
  99. }
  100. /*!
  101. * \reimp
  102. */
  103. QSize QtMaterialFloatingActionButton::sizeHint() const
  104. {
  105. Q_D(const QtMaterialFloatingActionButton);
  106. if (d->mini) {
  107. return QSize(QtMaterialFloatingActionButtonPrivate::MiniDiameter,
  108. QtMaterialFloatingActionButtonPrivate::MiniDiameter);
  109. } else {
  110. return QSize(QtMaterialFloatingActionButtonPrivate::DefaultDiameter,
  111. QtMaterialFloatingActionButtonPrivate::DefaultDiameter);
  112. }
  113. }
  114. void QtMaterialFloatingActionButton::setMini(bool state)
  115. {
  116. Q_D(QtMaterialFloatingActionButton);
  117. if (d->mini == state) {
  118. return;
  119. }
  120. d->mini = state;
  121. setFixedSize(d->diameter(), d->diameter());
  122. setFixedRippleRadius(state ? 30 : 50);
  123. d->setupProperties();
  124. updateClipPath();
  125. setGeometry(d->fabGeometry());
  126. update();
  127. }
  128. bool QtMaterialFloatingActionButton::isMini() const
  129. {
  130. Q_D(const QtMaterialFloatingActionButton);
  131. return d->mini;
  132. }
  133. void QtMaterialFloatingActionButton::setCorner(Qt::Corner corner)
  134. {
  135. Q_D(QtMaterialFloatingActionButton);
  136. if (d->corner == corner) {
  137. return;
  138. }
  139. d->corner = corner;
  140. setGeometry(d->fabGeometry());
  141. update();
  142. }
  143. Qt::Corner QtMaterialFloatingActionButton::corner() const
  144. {
  145. Q_D(const QtMaterialFloatingActionButton);
  146. return d->corner;
  147. }
  148. void QtMaterialFloatingActionButton::setOffset(int x, int y)
  149. {
  150. Q_D(QtMaterialFloatingActionButton);
  151. d->offsX = x;
  152. d->offsY = y;
  153. setGeometry(d->fabGeometry());
  154. update();
  155. }
  156. QSize QtMaterialFloatingActionButton::offset() const
  157. {
  158. Q_D(const QtMaterialFloatingActionButton);
  159. return QSize(d->offsX, d->offsY);
  160. }
  161. void QtMaterialFloatingActionButton::setXOffset(int x)
  162. {
  163. Q_D(QtMaterialFloatingActionButton);
  164. d->offsX = x;
  165. setGeometry(d->fabGeometry());
  166. update();
  167. }
  168. int QtMaterialFloatingActionButton::xOffset() const
  169. {
  170. Q_D(const QtMaterialFloatingActionButton);
  171. return d->offsX;
  172. }
  173. void QtMaterialFloatingActionButton::setYOffset(int y)
  174. {
  175. Q_D(QtMaterialFloatingActionButton);
  176. d->offsY = y;
  177. setGeometry(d->fabGeometry());
  178. update();
  179. }
  180. int QtMaterialFloatingActionButton::yOffset() const
  181. {
  182. Q_D(const QtMaterialFloatingActionButton);
  183. return d->offsY;
  184. }
  185. /*!
  186. * \reimp
  187. */
  188. bool QtMaterialFloatingActionButton::event(QEvent *event)
  189. {
  190. Q_D(QtMaterialFloatingActionButton);
  191. if (!parent()) {
  192. return QtMaterialRaisedButton::event(event);
  193. }
  194. switch (event->type())
  195. {
  196. case QEvent::ParentChange:
  197. {
  198. parent()->installEventFilter(this);
  199. setGeometry(d->fabGeometry());
  200. break;
  201. }
  202. case QEvent::ParentAboutToChange:
  203. {
  204. parent()->removeEventFilter(this);
  205. break;
  206. }
  207. default:
  208. break;
  209. }
  210. return QtMaterialRaisedButton::event(event);
  211. }
  212. /*!
  213. * \reimp
  214. */
  215. bool QtMaterialFloatingActionButton::eventFilter(QObject *obj, QEvent *event)
  216. {
  217. const QEvent::Type type = event->type();
  218. if (QEvent::Move == type || QEvent::Resize == type)
  219. {
  220. Q_D(QtMaterialFloatingActionButton);
  221. setGeometry(d->fabGeometry());
  222. }
  223. return QtMaterialRaisedButton::eventFilter(obj, event);
  224. }
  225. /*!
  226. * \reimp
  227. */
  228. void QtMaterialFloatingActionButton::paintEvent(QPaintEvent *event)
  229. {
  230. Q_UNUSED(event)
  231. Q_D(QtMaterialFloatingActionButton);
  232. QRect square = QRect(0, 0, d->diameter(), d->diameter());
  233. square.moveCenter(rect().center());
  234. QPainter painter(this);
  235. painter.setRenderHints(QPainter::Antialiasing);
  236. QBrush brush;
  237. brush.setStyle(Qt::SolidPattern);
  238. if (isEnabled()) {
  239. brush.setColor(backgroundColor());
  240. } else {
  241. brush.setColor(disabledBackgroundColor());
  242. }
  243. painter.setBrush(brush);
  244. painter.setPen(Qt::NoPen);
  245. painter.drawEllipse(square);
  246. QRect iconGeometry(0, 0, d->iconSize(), d->iconSize());
  247. iconGeometry.moveCenter(square.center());
  248. QPixmap pixmap = icon().pixmap(QSize(d->iconSize(), d->iconSize()));
  249. QPainter icon(&pixmap);
  250. icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
  251. icon.fillRect(pixmap.rect(), isEnabled() ? foregroundColor()
  252. : disabledForegroundColor());
  253. painter.drawPixmap(iconGeometry, pixmap);
  254. }
  255. void QtMaterialFloatingActionButton::updateClipPath()
  256. {
  257. Q_D(QtMaterialFloatingActionButton);
  258. QPainterPath path;
  259. path.addEllipse(0, 0, d->diameter(), d->diameter());
  260. d->rippleOverlay->setClipPath(path);
  261. }