feat: add cancel animation for drag to undock operation

https://github.com/linuxdeepin/internal-discussion/issues/663

Change-Id: I92daa3835fb6c5add9fcd5d1619e3a99d92d0b1f
This commit is contained in:
listenerri 2019-01-17 11:00:40 +08:00
parent 3fbfabd340
commit bc4608b858
Notes: gerrit 2019-01-18 12:53:13 +08:00
Verified+1: <jenkins@deepin.com>
Code-Review+2: listenerri <listenerri@gmail.com>
Submitted-by: listenerri <listenerri@gmail.com>
Submitted-at: Fri, 18 Jan 2019 12:53:13 +0800
Reviewed-on: https://cr.deepin.io/41378
Project: dde/dde-dock
Branch: refs/heads/dev/animations
7 changed files with 77 additions and 32 deletions

View File

@ -163,18 +163,28 @@ void AppItem::undock()
QWidget *AppItem::appDragWidget()
{
return static_cast<AppDrag *>(m_drag)->appDragWidget();
if (m_drag) {
return m_drag->appDragWidget();
}
return nullptr;
}
void AppItem::setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry)
{
static_cast<AppDrag *>(m_drag)->appDragWidget()->setDockInfo(dockPosition, dockGeometry);
if (m_drag) {
m_drag->appDragWidget()->setDockInfo(dockPosition, dockGeometry);
}
}
void AppItem::moveEvent(QMoveEvent *e)
{
DockItem::moveEvent(e);
if (m_drag) {
m_drag->appDragWidget()->setOriginPos(mapToGlobal(appIconPosition()));
}
m_updateIconGeometryTimer->start();
}
@ -278,16 +288,10 @@ void AppItem::paintEvent(QPaintEvent *e)
return;
// icon
const QPixmap &pixmap = m_appIcon;
if (pixmap.isNull())
if (m_appIcon.isNull())
return;
// icon pos
const auto ratio = qApp->devicePixelRatio();
const int iconX = itemRect.center().x() - pixmap.rect().center().x() / ratio;
const int iconY = itemRect.center().y() - pixmap.rect().center().y() / ratio;
painter.drawPixmap(iconX, iconY, pixmap);
painter.drawPixmap(appIconPosition(), m_appIcon);
}
void AppItem::mouseReleaseEvent(QMouseEvent *e)
@ -468,8 +472,16 @@ void AppItem::startDrag()
m_drag = new AppDrag(this);
m_drag->setMimeData(new QMimeData);
// handle drag finished here
connect(m_drag->appDragWidget(), &AppDragWidget::destroyed, this, [=] {
m_dragging = false;
setVisible(true);
update();
});
if (m_wmHelper->hasComposite()) {
m_drag->setPixmap(dragPix);
m_drag->appDragWidget()->setOriginPos(mapToGlobal(appIconPosition()));
emit dragStarted();
m_drag->exec(Qt::MoveAction);
} else {
@ -487,10 +499,6 @@ void AppItem::startDrag()
m_itemEntryInter->RequestUndock();
}
}
m_dragging = false;
setVisible(true);
update();
}
bool AppItem::hasAttention() const
@ -501,6 +509,17 @@ bool AppItem::hasAttention() const
return false;
}
QPoint AppItem::appIconPosition() const
{
const auto ratio = qApp->devicePixelRatio();
const QRectF itemRect = rect();
const QRectF iconRect = m_appIcon.rect();
const qreal iconX = itemRect.center().x() - iconRect.center().x() / ratio;
const qreal iconY = itemRect.center().y() - iconRect.center().y() / ratio;
return QPoint(iconX, iconY);
}
void AppItem::updateWindowInfos(const WindowInfoMap &info)
{
m_windowInfos = info;

View File

@ -86,6 +86,8 @@ private:
void startDrag();
bool hasAttention() const;
QPoint appIconPosition() const;
private slots:
void updateWindowInfos(const WindowInfoMap &info);
void refershIcon() Q_DECL_OVERRIDE;
@ -106,7 +108,7 @@ private:
DWindowManagerHelper *m_wmHelper;
AppDrag *m_drag;
QPointer<AppDrag> m_drag;
bool m_dragging;
bool m_active;

View File

@ -25,9 +25,15 @@ AppDrag::AppDrag(QObject *dragSource) : QDrag(dragSource)
{
// delete by itself
m_appDragWidget = new AppDragWidget;
m_appDragWidget->setVisible(false);
}
AppDrag::~AppDrag() { }
AppDrag::~AppDrag() {
// delete when AppDragWidget is invisible
if (m_appDragWidget && !m_appDragWidget->isVisible()) {
m_appDragWidget->deleteLater();
}
}
void AppDrag::setPixmap(const QPixmap &pix)
{

View File

@ -40,13 +40,10 @@ public:
Qt::DropAction exec(Qt::DropActions supportedActions = Qt::MoveAction);
Qt::DropAction exec(Qt::DropActions supportedActions, Qt::DropAction defaultAction);
void setOpacity(qreal opacity);
void showDropAnim();
AppDragWidget *appDragWidget();
private:
AppDragWidget *m_appDragWidget;
QPointer<AppDragWidget> m_appDragWidget;
};
#endif /* DRAGAPP_H */

View File

@ -26,7 +26,7 @@
class AppGraphicsObject : public QGraphicsObject
{
public:
AppGraphicsObject(QGraphicsItem *parent = Q_NULLPTR) : QGraphicsObject(parent) {};
AppGraphicsObject(QGraphicsItem *parent = Q_NULLPTR) : QGraphicsObject(parent) {}
~AppGraphicsObject() { }
void setAppPixmap(QPixmap pix)
@ -47,14 +47,14 @@ public:
QRectF boundingRect() const Q_DECL_OVERRIDE
{
return m_appPixmap.rect();
};
}
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) Q_DECL_OVERRIDE
{
Q_ASSERT(!m_appPixmap.isNull());
painter->drawPixmap(QPoint(0, 0), m_appPixmap);
};
}
private:
QPixmap m_appPixmap;
@ -68,7 +68,8 @@ AppDragWidget::AppDragWidget(QWidget *parent) :
m_animScale(new QPropertyAnimation(m_object, "scale", this)),
m_animRotation(new QPropertyAnimation(m_object, "rotation", this)),
m_animOpacity(new QPropertyAnimation(m_object, "opacity", this)),
m_animGroup(new QParallelAnimationGroup(this))
m_animGroup(new QParallelAnimationGroup(this)),
m_goBackAnim(new QPropertyAnimation(this, "pos", this))
{
m_scene->addItem(m_object);
setScene(m_scene);
@ -92,20 +93,22 @@ AppDragWidget::AppDragWidget(QWidget *parent) :
m_followMouseTimer->start();
}
AppDragWidget::~AppDragWidget() { }
AppDragWidget::~AppDragWidget() {
}
void AppDragWidget::mouseMoveEvent(QMouseEvent *event)
{
QGraphicsView::mouseMoveEvent(event);
// hide widget when receiving mouseMoveEvent because this means drag-and-drop has been finished
hide();
if (m_goBackAnim->state() != QPropertyAnimation::State::Running
&& m_animGroup->state() != QParallelAnimationGroup::Running) {
hide();
}
}
void AppDragWidget::dragEnterEvent(QDragEnterEvent *event)
{
event->accept();
m_dragStartPoint = event->pos();
}
void AppDragWidget::dragMoveEvent(QDragMoveEvent *event)
@ -128,7 +131,7 @@ void AppDragWidget::dropEvent(QDropEvent *event)
AppItem *appItem = static_cast<AppItem *>(event->source());
appItem->undock();
} else {
hide();
showGoBackAnimation();;
}
}
@ -139,7 +142,7 @@ void AppDragWidget::hideEvent(QHideEvent *event)
void AppDragWidget::setAppPixmap(const QPixmap &pix)
{
setFixedSize(pix.size() + QSize(10,10));
setFixedSize(pix.size());
m_object->setAppPixmap(pix);
m_object->setTransformOriginPoint(pix.rect().center());
@ -151,6 +154,11 @@ void AppDragWidget::setDockInfo(Dock::Position dockPosition, const QRect &dockGe
m_dockGeometry = dockGeometry;
}
void AppDragWidget::setOriginPos(const QPoint position)
{
m_originPoint = position;
}
void AppDragWidget::initAnimations()
{
m_animScale->setDuration(300);
@ -171,6 +179,7 @@ void AppDragWidget::initAnimations()
connect(m_animGroup, &QParallelAnimationGroup::stateChanged,
this, &AppDragWidget::onRemoveAnimationStateChanged);
connect(m_goBackAnim, &QPropertyAnimation::finished, this, &AppDragWidget::hide);
}
void AppDragWidget::showRemoveAnimation()
@ -182,6 +191,14 @@ void AppDragWidget::showRemoveAnimation()
m_animGroup->start();
}
void AppDragWidget::showGoBackAnimation()
{
m_goBackAnim->setDuration(300);
m_goBackAnim->setStartValue(pos());
m_goBackAnim->setEndValue(m_originPoint);
m_goBackAnim->start();
}
void AppDragWidget::onRemoveAnimationStateChanged(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState)
{

View File

@ -43,6 +43,7 @@ public:
void setAppPixmap(const QPixmap &pix);
void setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry);
void setOriginPos(const QPoint position);
protected:
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
@ -54,6 +55,7 @@ protected:
private:
void initAnimations();
void showRemoveAnimation();
void showGoBackAnimation();
void onRemoveAnimationStateChanged(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState);
bool isRemoveAble();
@ -66,10 +68,11 @@ private:
QPropertyAnimation *m_animRotation;
QPropertyAnimation *m_animOpacity;
QParallelAnimationGroup *m_animGroup;
QPropertyAnimation *m_goBackAnim;
Dock::Position m_dockPosition;
QRect m_dockGeometry;
QPoint m_dragStartPoint;
QPoint m_originPoint;
};
#endif /* APPDRAGWIDGET_H */

View File

@ -312,8 +312,9 @@ void MainPanel::dragLeaveEvent(QDragLeaveEvent *e)
if (DraggingItem) {
DockItem::ItemType type = DraggingItem->itemType();
if (type != DockItem::Plugins && type != DockItem::TrayPlugin)
if (type != DockItem::Plugins && type != DockItem::TrayPlugin) {
DraggingItem->hide();
}
}
}