refactor: app item swing animation

Change-Id: Ia794194e56781c63eb7516b3c1fd389de17ccab8
This commit is contained in:
listenerri 2018-07-04 14:18:12 +08:00
parent 052b6b29d2
commit 16f20ae454
Notes: gerrit 2018-07-05 13:28:26 +08:00
Verified+1: <jenkins@deepin.com>
Code-Review+2: hualet <mr.asianwang@gmail.com>
Submitted-by: listenerri <listenerri@gmail.com>
Submitted-at: Thu, 05 Jul 2018 13:28:26 +0800
Reviewed-on: https://cr.deepin.io/36366
Project: dde/dde-dock
Branch: refs/heads/master
3 changed files with 156 additions and 121 deletions

View File

@ -24,6 +24,7 @@
#include "util/themeappicon.h"
#include "util/imagefactory.h"
#include "xcb/xcb_misc.h"
#include "components/appswingeffectbuilder.h"
#include <X11/X.h>
#include <X11/Xlib.h>
@ -39,67 +40,6 @@
#define APP_DRAG_THRESHOLD 20
const static qreal Frames[] = { 0,
0.327013,
0.987033,
1.77584,
2.61157,
3.45043,
4.26461,
5.03411,
5.74306,
6.37782,
6.92583,
7.37484,
7.71245,
7.92557,
8, 7.86164,
7.43184,
6.69344,
5.64142,
4.2916,
2.68986,
0.91694,
-0.91694,
-2.68986,
-4.2916,
-5.64142,
-6.69344,
-7.43184,
-7.86164,
-8,
-7.86164,
-7.43184,
-6.69344,
-5.64142,
-4.2916,
-2.68986,
-0.91694,
0.91694,
2.68986,
4.2916,
5.64142,
6.69344,
7.43184,
7.86164,
8,
7.93082,
7.71592,
7.34672,
6.82071,
6.1458,
5.34493,
4.45847,
3.54153,
2.65507,
1.8542,
1.17929,
0.653279,
0.28408,
0.0691776,
0,
};
int AppItem::IconBaseSize;
QPoint AppItem::MousePressPos;
@ -109,8 +49,8 @@ AppItem::AppItem(const QDBusObjectPath &entry, QWidget *parent)
m_appPreviewTips(new PreviewContainer(this)),
m_itemEntryInter(new DockEntryInter("com.deepin.dde.daemon.Dock", entry.path(), QDBusConnection::sessionBus(), this)),
m_swingEffectView(new QGraphicsView(this)),
m_itemScene(new QGraphicsScene(this)),
m_swingEffectView(nullptr),
m_itemAnimation(nullptr),
m_dragging(false),
@ -125,10 +65,7 @@ AppItem::AppItem(const QDBusObjectPath &entry, QWidget *parent)
m_smallWatcher(new QFutureWatcher<QPixmap>(this)),
m_largeWatcher(new QFutureWatcher<QPixmap>(this))
{
m_swingEffectView->setAttribute(Qt::WA_TransparentForMouseEvents);
QHBoxLayout *centralLayout = new QHBoxLayout;
centralLayout->addWidget(m_swingEffectView);
centralLayout->setMargin(0);
centralLayout->setSpacing(0);
@ -136,16 +73,6 @@ AppItem::AppItem(const QDBusObjectPath &entry, QWidget *parent)
setAcceptDrops(true);
setLayout(centralLayout);
m_swingEffectView->setScene(m_itemScene);
m_swingEffectView->setAlignment(Qt::AlignCenter);
m_swingEffectView->setVisible(false);
m_swingEffectView->setFrameStyle(QFrame::NoFrame);
m_swingEffectView->setContentsMargins(0, 0, 0, 0);
m_swingEffectView->setRenderHints(QPainter::SmoothPixmapTransform);
m_swingEffectView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
m_swingEffectView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_swingEffectView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_id = m_itemEntryInter->id();
m_active = m_itemEntryInter->isActive();
@ -238,7 +165,7 @@ void AppItem::paintEvent(QPaintEvent *e)
{
DockItem::paintEvent(e);
if (m_dragging || (m_swingEffectView->isVisible() && DockDisplayMode != Fashion))
if (m_dragging || (m_swingEffectView != nullptr && DockDisplayMode != Fashion))
return;
QPainter painter(this);
@ -322,7 +249,7 @@ void AppItem::paintEvent(QPaintEvent *e)
}
}
if (m_swingEffectView->isVisible())
if (m_swingEffectView != nullptr)
return;
// icon
@ -602,62 +529,42 @@ void AppItem::cancelAndHidePreview()
void AppItem::playSwingEffect()
{
// NOTE(sbw): return if animation view already playing
if (m_swingEffectView->isVisible())
if (m_swingEffectView != nullptr)
return;
stopSwingEffect();
if (!m_itemAnimation.timeLine())
{
QTimeLine *tl = new QTimeLine(1200, this);
tl->setFrameRange(0, 60);
tl->setLoopCount(1);
tl->setEasingCurve(QEasingCurve::Linear);
tl->setStartFrame(0);
m_itemAnimation.setTimeLine(tl);
QPair<QGraphicsView *, QGraphicsItemAnimation *> pair = SwingEffect(
this, m_appIcon, rect(), qApp->devicePixelRatio());
m_swingEffectView = pair.first;
m_itemAnimation = pair.second;
QTimeLine *tl = m_itemAnimation->timeLine();
connect(tl, &QTimeLine::stateChanged, [=](QTimeLine::State newState) {
if (newState == QTimeLine::NotRunning) {
m_swingEffectView->hide();
layout()->removeWidget(m_swingEffectView);
m_swingEffectView = nullptr;
m_itemAnimation = nullptr;
checkAttentionEffect();
}
});
const auto ratio = qApp->devicePixelRatio();
const QRect r = rect();
const QPixmap &icon = m_appIcon;
QGraphicsPixmapItem *item = m_itemScene->addPixmap(icon);
item->setTransformationMode(Qt::SmoothTransformation);
item->setPos(QPointF(r.center()) - QPointF(icon.rect().center()) / ratio);
m_itemAnimation.setItem(item);
m_itemScene->setSceneRect(r);
m_swingEffectView->setSceneRect(r);
m_swingEffectView->setFixedSize(r.size());
const int px = qreal(-icon.rect().center().x()) / ratio;
const int py = qreal(-icon.rect().center().y()) / ratio - 18.;
const QPoint pos = r.center() + QPoint(0, 18);
for (int i(0); i != 60; ++i)
{
m_itemAnimation.setPosAt(i / 60.0, pos);
m_itemAnimation.setTranslationAt(i / 60.0, px, py);
m_itemAnimation.setRotationAt(i / 60.0, Frames[i]);
}
QTimeLine *tl = m_itemAnimation.timeLine();
connect(tl, &QTimeLine::finished, m_swingEffectView, &QGraphicsView::hide);
connect(tl, &QTimeLine::finished, this, &AppItem::checkAttentionEffect);
layout()->addWidget(m_swingEffectView);
tl->start();
m_swingEffectView->setVisible(true);
}
void AppItem::stopSwingEffect()
{
if (m_swingEffectView == nullptr || m_itemAnimation == nullptr)
return;
// stop swing effect
m_swingEffectView->setVisible(false);
if (m_itemAnimation.timeLine() && m_itemAnimation.timeLine()->state() != QTimeLine::NotRunning)
m_itemAnimation.timeLine()->stop();
m_itemAnimation.clear();
if (!m_itemScene->items().isEmpty())
m_itemScene->clear();
if (m_itemAnimation->timeLine() && m_itemAnimation->timeLine()->state() != QTimeLine::NotRunning)
m_itemAnimation->timeLine()->stop();
}
void AppItem::checkAttentionEffect()

View File

@ -95,8 +95,7 @@ private:
DockEntryInter *m_itemEntryInter;
QGraphicsView *m_swingEffectView;
QGraphicsScene *m_itemScene;
QGraphicsItemAnimation m_itemAnimation;
QGraphicsItemAnimation *m_itemAnimation;
bool m_dragging;
bool m_active;

View File

@ -0,0 +1,129 @@
#ifndef SWINGEFFECT
#define SWINGEFFECT
#include <QGraphicsView>
#include <QGraphicsItemAnimation>
#include <QGraphicsPixmapItem>
#include <QTimeLine>
const static qreal Frames[] = { 0,
0.327013,
0.987033,
1.77584,
2.61157,
3.45043,
4.26461,
5.03411,
5.74306,
6.37782,
6.92583,
7.37484,
7.71245,
7.92557,
8, 7.86164,
7.43184,
6.69344,
5.64142,
4.2916,
2.68986,
0.91694,
-0.91694,
-2.68986,
-4.2916,
-5.64142,
-6.69344,
-7.43184,
-7.86164,
-8,
-7.86164,
-7.43184,
-6.69344,
-5.64142,
-4.2916,
-2.68986,
-0.91694,
0.91694,
2.68986,
4.2916,
5.64142,
6.69344,
7.43184,
7.86164,
8,
7.93082,
7.71592,
7.34672,
6.82071,
6.1458,
5.34493,
4.45847,
3.54153,
2.65507,
1.8542,
1.17929,
0.653279,
0.28408,
0.0691776,
0,
};
static QPair<QGraphicsView *, QGraphicsItemAnimation *> SwingEffect(
QWidget *parent, const QPixmap &icon, const QRect & rect, const qreal devicePixelRatio)
{
QGraphicsView *swingEffectView = new QGraphicsView(parent);
QGraphicsScene *itemScene = new QGraphicsScene(parent);
QGraphicsItemAnimation *itemAnimation = new QGraphicsItemAnimation(parent);
swingEffectView->setAttribute(Qt::WA_TransparentForMouseEvents);
swingEffectView->setScene(itemScene);
swingEffectView->setAlignment(Qt::AlignCenter);
swingEffectView->setFrameStyle(QFrame::NoFrame);
swingEffectView->setContentsMargins(0, 0, 0, 0);
swingEffectView->setRenderHints(QPainter::SmoothPixmapTransform);
swingEffectView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
swingEffectView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
swingEffectView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QTimeLine *tl = itemAnimation->timeLine();
if (!tl)
{
tl = new QTimeLine(1200, parent);
tl->setFrameRange(0, 60);
tl->setLoopCount(1);
tl->setEasingCurve(QEasingCurve::Linear);
tl->setStartFrame(0);
itemAnimation->setTimeLine(tl);
}
QGraphicsPixmapItem *item = itemScene->addPixmap(icon);
item->setTransformationMode(Qt::SmoothTransformation);
item->setPos(QPointF(rect.center()) - QPointF(icon.rect().center()) / devicePixelRatio);
itemAnimation->setItem(item);
itemScene->setSceneRect(rect);
swingEffectView->setSceneRect(rect);
swingEffectView->setFixedSize(rect.size());
const int px = qreal(-icon.rect().center().x()) / devicePixelRatio;
const int py = qreal(-icon.rect().center().y()) / devicePixelRatio - 18.;
const QPoint pos = rect.center() + QPoint(0, 18);
for (int i(0); i != 60; ++i)
{
itemAnimation->setPosAt(i / 60.0, pos);
itemAnimation->setTranslationAt(i / 60.0, px, py);
itemAnimation->setRotationAt(i / 60.0, Frames[i]);
}
QObject::connect(tl, &QTimeLine::stateChanged, [=](QTimeLine::State newState) {
if (newState == QTimeLine::NotRunning) {
itemScene->deleteLater();
swingEffectView->deleteLater();
itemAnimation->deleteLater();
}
});
return QPair<QGraphicsView *, QGraphicsItemAnimation *>(swingEffectView, itemAnimation);
}
#endif /* ifndef SWINGEFFECT */