fade_animation.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "ui/effects/fade_animation.h"
  8. #include "ui/ui_utility.h"
  9. #include "ui/painter.h"
  10. namespace Ui {
  11. namespace {
  12. constexpr int kWideScale = 5;
  13. } // namespace
  14. FadeAnimation::FadeAnimation(TWidget *widget, float64 scale)
  15. : _widget(widget)
  16. , _scale(scale) {
  17. }
  18. bool FadeAnimation::paint(QPainter &p) {
  19. if (_cache.isNull()) return false;
  20. const auto cache = _cache;
  21. auto opacity = _animation.value(_visible ? 1. : 0.);
  22. p.setOpacity(opacity);
  23. if (_scale < 1.) {
  24. PainterHighQualityEnabler hq(p);
  25. auto targetRect = QRect(
  26. (1 - kWideScale) / 2 * _size.width(),
  27. (1 - kWideScale) / 2 * _size.height(),
  28. kWideScale * _size.width(),
  29. kWideScale * _size.height());
  30. auto scale = opacity + (1. - opacity) * _scale;
  31. auto shownWidth = anim::interpolate(
  32. (1 - kWideScale) / 2 * _size.width(),
  33. 0,
  34. scale);
  35. auto shownHeight = anim::interpolate(
  36. (1 - kWideScale) / 2 * _size.height(),
  37. 0,
  38. scale);
  39. auto margins = QMargins(
  40. shownWidth,
  41. shownHeight,
  42. shownWidth,
  43. shownHeight);
  44. p.drawPixmap(targetRect.marginsAdded(margins), cache);
  45. } else {
  46. p.drawPixmap(0, 0, cache);
  47. }
  48. return true;
  49. }
  50. void FadeAnimation::refreshCache() {
  51. if (!_cache.isNull()) {
  52. _cache = QPixmap();
  53. _cache = grabContent();
  54. Assert(!_cache.isNull());
  55. }
  56. }
  57. QPixmap FadeAnimation::grabContent() {
  58. SendPendingMoveResizeEvents(_widget);
  59. _size = _widget->size();
  60. const auto pixelRatio = style::DevicePixelRatio();
  61. if (_size.isEmpty()) {
  62. auto image = QImage(
  63. pixelRatio,
  64. pixelRatio,
  65. QImage::Format_ARGB32_Premultiplied);
  66. image.fill(Qt::transparent);
  67. return PixmapFromImage(std::move(image));
  68. }
  69. auto widgetContent = GrabWidget(_widget);
  70. if (_scale < 1.) {
  71. auto result = QImage(kWideScale * _size * pixelRatio, QImage::Format_ARGB32_Premultiplied);
  72. result.setDevicePixelRatio(pixelRatio);
  73. result.fill(Qt::transparent);
  74. {
  75. Painter p(&result);
  76. p.drawPixmap((kWideScale - 1) / 2 * _size.width(), (kWideScale - 1) / 2 * _size.height(), widgetContent);
  77. }
  78. return PixmapFromImage(std::move(result));
  79. }
  80. return widgetContent;
  81. }
  82. void FadeAnimation::setFinishedCallback(FinishedCallback &&callback) {
  83. _finishedCallback = std::move(callback);
  84. }
  85. void FadeAnimation::setUpdatedCallback(UpdatedCallback &&callback) {
  86. _updatedCallback = std::move(callback);
  87. }
  88. void FadeAnimation::show() {
  89. _visible = true;
  90. stopAnimation();
  91. }
  92. void FadeAnimation::hide() {
  93. _visible = false;
  94. stopAnimation();
  95. }
  96. void FadeAnimation::stopAnimation() {
  97. _animation.stop();
  98. if (!_cache.isNull()) {
  99. _cache = QPixmap();
  100. if (_finishedCallback) {
  101. _finishedCallback();
  102. }
  103. }
  104. if (_visible == _widget->isHidden()) {
  105. _widget->setVisible(_visible);
  106. }
  107. }
  108. void FadeAnimation::fadeIn(int duration) {
  109. if (_visible) return;
  110. _visible = true;
  111. startAnimation(duration);
  112. }
  113. void FadeAnimation::fadeOut(int duration) {
  114. if (!_visible) return;
  115. _visible = false;
  116. startAnimation(duration);
  117. }
  118. void FadeAnimation::startAnimation(int duration) {
  119. if (_cache.isNull()) {
  120. _cache = grabContent();
  121. Assert(!_cache.isNull());
  122. }
  123. auto from = _visible ? 0. : 1.;
  124. auto to = _visible ? 1. : 0.;
  125. _animation.start([this]() { updateCallback(); }, from, to, duration);
  126. updateCallback();
  127. if (_widget->isHidden()) {
  128. _widget->show();
  129. }
  130. }
  131. void FadeAnimation::updateCallback() {
  132. _widget->update();
  133. if (_updatedCallback) {
  134. _updatedCallback(_animation.value(_visible ? 1. : 0.));
  135. }
  136. if (!_animation.animating()) {
  137. stopAnimation();
  138. }
  139. }
  140. } // namespace Ui