diff --git a/gyp/sources.txt b/gyp/sources.txt index 9271d78..3c8a8db 100644 --- a/gyp/sources.txt +++ b/gyp/sources.txt @@ -14,6 +14,8 @@ <(src_loc)/ui/effects/radial_animation.h <(src_loc)/ui/effects/ripple_animation.cpp <(src_loc)/ui/effects/ripple_animation.h +<(src_loc)/ui/effects/slide_animation.cpp +<(src_loc)/ui/effects/slide_animation.h <(src_loc)/ui/image/image_prepare.cpp <(src_loc)/ui/image/image_prepare.h <(src_loc)/ui/layers/box_content.cpp diff --git a/ui/effects/slide_animation.cpp b/ui/effects/slide_animation.cpp new file mode 100644 index 0000000..7ff2fa3 --- /dev/null +++ b/ui/effects/slide_animation.cpp @@ -0,0 +1,80 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/effects/slide_animation.h" + +#include + +namespace Ui { + +void SlideAnimation::setSnapshots( + QPixmap leftSnapshot, + QPixmap rightSnapshot) { + Expects(!leftSnapshot.isNull()); + Expects(!rightSnapshot.isNull()); + + _leftSnapshot = std::move(leftSnapshot); + _rightSnapshot = std::move(rightSnapshot); + _leftSnapshot.setDevicePixelRatio(style::DevicePixelRatio()); + _rightSnapshot.setDevicePixelRatio(style::DevicePixelRatio()); +} + +void SlideAnimation::paintFrame(QPainter &p, int x, int y, int outerWidth) { + const auto dt = _animation.value(1.); + if (!animating()) { + return; + } + + const auto pixelRatio = style::DevicePixelRatio(); + const auto easeOut = anim::easeOutCirc(1., dt); + const auto easeIn = anim::easeInCirc(1., dt); + const auto arrivingAlpha = easeIn; + const auto departingAlpha = 1. - easeOut; + const auto leftCoord = _slideLeft + ? anim::interpolate(-_leftSnapshotWidth, 0, easeOut) + : anim::interpolate(0, -_leftSnapshotWidth, easeIn); + const auto leftAlpha = (_slideLeft ? arrivingAlpha : departingAlpha); + const auto rightCoord = _slideLeft + ? anim::interpolate(0, _rightSnapshotWidth, easeIn) + : anim::interpolate(_rightSnapshotWidth, 0, easeOut); + const auto rightAlpha = (_slideLeft ? departingAlpha : arrivingAlpha); + + if (_overflowHidden) { + const auto leftWidth = (_leftSnapshotWidth + leftCoord); + if (leftWidth > 0) { + p.setOpacity(leftAlpha); + p.drawPixmap( + x, + y, + leftWidth, + _leftSnapshotHeight, + _leftSnapshot, + (_leftSnapshot.width() - leftWidth * pixelRatio), + 0, + leftWidth * pixelRatio, + _leftSnapshot.height()); + } + const auto rightWidth = _rightSnapshotWidth - rightCoord; + if (rightWidth > 0) { + p.setOpacity(rightAlpha); + p.drawPixmap( + x + rightCoord, + y, + _rightSnapshot, + 0, + 0, + rightWidth * pixelRatio, + _rightSnapshot.height()); + } + } else { + p.setOpacity(leftAlpha); + p.drawPixmap(x + leftCoord, y, _leftSnapshot); + p.setOpacity(rightAlpha); + p.drawPixmap(x + rightCoord, y, _rightSnapshot); + } +} + +} // namespace Ui diff --git a/ui/effects/slide_animation.h b/ui/effects/slide_animation.h new file mode 100644 index 0000000..d79d062 --- /dev/null +++ b/ui/effects/slide_animation.h @@ -0,0 +1,58 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#pragma once + +#include "ui/effects/animations.h" + +namespace Ui { + +class SlideAnimation { +public: + void setSnapshots(QPixmap leftSnapshot, QPixmap rightSnapshot); + + void setOverflowHidden(bool hidden) { + _overflowHidden = hidden; + } + + template + void start(bool slideLeft, Lambda &&updateCallback, float64 duration); + + void paintFrame(QPainter &p, int x, int y, int outerWidth); + + bool animating() const { + return _animation.animating(); + } + +private: + Ui::Animations::Simple _animation; + QPixmap _leftSnapshot; + QPixmap _rightSnapshot; + bool _slideLeft = false; + bool _overflowHidden = true; + int _leftSnapshotWidth = 0; + int _leftSnapshotHeight = 0; + int _rightSnapshotWidth = 0; + +}; + +template +void SlideAnimation::start( + bool slideLeft, + Lambda &&updateCallback, + float64 duration) { + _slideLeft = slideLeft; + if (_slideLeft) { + std::swap(_leftSnapshot, _rightSnapshot); + } + const auto pixelRatio = style::DevicePixelRatio(); + _leftSnapshotWidth = _leftSnapshot.width() / pixelRatio; + _leftSnapshotHeight = _leftSnapshot.height() / pixelRatio; + _rightSnapshotWidth = _rightSnapshot.width() / pixelRatio; + _animation.start(std::forward(updateCallback), 0., 1., duration); +} + +} // namespace Ui