gradient_round_button.cpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "ui/widgets/gradient_round_button.h"
  8. #include "ui/image/image_prepare.h"
  9. #include "styles/style_boxes.h"
  10. namespace Ui {
  11. GradientButton::GradientButton(QWidget *widget, QGradientStops stops)
  12. : RippleButton(widget, st::defaultRippleAnimation)
  13. , _stops(std::move(stops)) {
  14. }
  15. void GradientButton::paintEvent(QPaintEvent *e) {
  16. QPainter p(this);
  17. validateBg();
  18. p.drawImage(0, 0, _bg);
  19. paintGlare(p);
  20. const auto ripple = QColor(0, 0, 0, 36);
  21. paintRipple(p, 0, 0, &ripple);
  22. }
  23. void GradientButton::paintGlare(QPainter &p) {
  24. if (!_glare.glare.birthTime) {
  25. return;
  26. }
  27. const auto progress = _glare.progress(crl::now());
  28. const auto x = (-_glare.width) + (width() + _glare.width * 2) * progress;
  29. const auto h = height();
  30. const auto edgeWidth = _glare.width + st::roundRadiusLarge;
  31. if (x > edgeWidth && x < (width() - edgeWidth)) {
  32. p.drawTiledPixmap(x, 0, _glare.width, h, _glare.pixmap, 0, 0);
  33. } else {
  34. auto frame = QImage(
  35. QSize(_glare.width, h) * style::DevicePixelRatio(),
  36. QImage::Format_ARGB32_Premultiplied);
  37. frame.setDevicePixelRatio(style::DevicePixelRatio());
  38. frame.fill(Qt::transparent);
  39. {
  40. auto q = QPainter(&frame);
  41. q.drawTiledPixmap(0, 0, _glare.width, h, _glare.pixmap, 0, 0);
  42. q.setCompositionMode(QPainter::CompositionMode_DestinationIn);
  43. q.drawImage(-x, 0, _bg, 0, 0);
  44. }
  45. p.drawImage(x, 0, frame);
  46. }
  47. }
  48. void GradientButton::validateBg() {
  49. const auto factor = devicePixelRatio();
  50. if (!_bg.isNull()
  51. && (_bg.devicePixelRatio() == factor)
  52. && (_bg.size() == size() * factor)) {
  53. return;
  54. }
  55. _bg = QImage(size() * factor, QImage::Format_ARGB32_Premultiplied);
  56. _bg.setDevicePixelRatio(factor);
  57. auto p = QPainter(&_bg);
  58. auto gradient = QLinearGradient(QPointF(0, 0), QPointF(width(), 0));
  59. gradient.setStops(_stops);
  60. p.fillRect(rect(), gradient);
  61. p.end();
  62. _bg = Images::Round(std::move(_bg), ImageRoundRadius::Large);
  63. }
  64. void GradientButton::setGlarePaused(bool paused) {
  65. _glare.paused = paused;
  66. }
  67. void GradientButton::validateGlare() {
  68. _glare.validate(
  69. st::premiumButtonFg->c,
  70. [=] { update(); },
  71. st::gradientButtonGlareTimeout,
  72. st::gradientButtonGlareDuration);
  73. }
  74. void GradientButton::startGlareAnimation() {
  75. validateGlare();
  76. }
  77. } // namespace Ui