From 32d2837e52caa916e85b39cd7e67cf6fd80d8cc9 Mon Sep 17 00:00:00 2001 From: Marcin Miklas Date: Wed, 29 Dec 2010 13:58:07 +0100 Subject: New: Sliding and crossfading animation of navigationbar content. RevBy: Dominik Details: Old content of navigationbar are crossfaded with new content + old content slide out and new slide in. Animation can be also used with other widgets. --- .../widget/mcontentfadeandslideanimation.cpp | 221 +++++++++++++++++++++ .../widget/mcontentfadeandslideanimation.h | 54 +++++ .../widget/mcontentfadeandslideanimation_p.h | 63 ++++++ src/corelib/animation/widget/widget.pri | 3 + .../style/mcontentfadeandslideanimationstyle.h | 57 ++++++ src/corelib/style/style.pri | 1 + src/corelib/widgets/mapplicationwindow.cpp | 16 +- src/corelib/widgets/mapplicationwindow_p.h | 3 + src/views/mnavigationbarview.cpp | 13 +- src/views/mnavigationbarview_p.h | 2 + 10 files changed, 429 insertions(+), 4 deletions(-) create mode 100644 src/corelib/animation/widget/mcontentfadeandslideanimation.cpp create mode 100644 src/corelib/animation/widget/mcontentfadeandslideanimation.h create mode 100644 src/corelib/animation/widget/mcontentfadeandslideanimation_p.h create mode 100644 src/corelib/style/mcontentfadeandslideanimationstyle.h diff --git a/src/corelib/animation/widget/mcontentfadeandslideanimation.cpp b/src/corelib/animation/widget/mcontentfadeandslideanimation.cpp new file mode 100644 index 00000000..c594cb86 --- /dev/null +++ b/src/corelib/animation/widget/mcontentfadeandslideanimation.cpp @@ -0,0 +1,221 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ +#include "mcontentfadeandslideanimation.h" +#include "mcontentfadeandslideanimation_p.h" +#include +#include +#include +#include + +namespace { + const QPointF farFarAway(-100000, -100000); +} + +void SnapshotItem::updateSnapshot(QGraphicsWidget* target) +{ + QSize newSize = target->sceneTransform().mapRect(target->boundingRect()).size().toSize(); + + if (newSize != pixmap.size()) + pixmap = QPixmap(newSize); + + pixmap.fill(Qt::transparent); + + QPainter painter(&pixmap); + + const QPointF oldPos(target->pos()); + // move target far away so nothing is below + target->setPos(farFarAway); + target->scene()->render(&painter, QRectF(), target->sceneBoundingRect()); + target->setPos(oldPos); +} + +QRectF SnapshotItem::boundingRect() const +{ + return QRectF(0, 0, pixmap.width(), pixmap.height()); +} + +void SnapshotItem::paint(QPainter *painter, const QStyleOptionGraphicsItem */*option*/, QWidget */*widget*/) +{ + painter->drawPixmap(QPoint(0, 0), pixmap); +} + + +MContentFadeAndSlideAnimationPrivate::MContentFadeAndSlideAnimationPrivate() + : snapshotItem(0) + , contentItem(0) + , previous(0) + , fadeOut(0) + , slideOut(0) + , current(0) + , fadeIn(0) + , slideIn(0) + , currentWithDelay(0) + , delay(0) +{ +} + +void MContentFadeAndSlideAnimationPrivate::init() +{ + Q_Q(MContentFadeAndSlideAnimation); + + snapshotItem = new SnapshotItem; + + previous = new QParallelAnimationGroup(); + + fadeOut = new QPropertyAnimation(); + fadeOut->setPropertyName("opacity"); + fadeOut->setTargetObject(snapshotItem); + previous->addAnimation(fadeOut); + + slideOut = new QPropertyAnimation(); + slideOut->setPropertyName("pos"); + slideOut->setTargetObject(snapshotItem); + previous->addAnimation(slideOut); + + current = new QParallelAnimationGroup(); + + fadeIn = new QPropertyAnimation(); + fadeIn->setPropertyName("opacity"); + current->addAnimation(fadeIn); + + slideIn = new QPropertyAnimation(); + slideIn->setPropertyName("pos"); + current->addAnimation(slideIn); + + currentWithDelay = new QSequentialAnimationGroup(); + delay = new QPauseAnimation; + + currentWithDelay->addAnimation(delay); + currentWithDelay->addAnimation(current); + + q->addAnimation(previous); + q->addAnimation(currentWithDelay); +} + + +MContentFadeAndSlideAnimation::MContentFadeAndSlideAnimation(QObject *parent) : + MAbstractWidgetAnimation(new MContentFadeAndSlideAnimationPrivate, parent) +{ + Q_D(MContentFadeAndSlideAnimation); + + d->init(); +} + +MContentFadeAndSlideAnimation::~MContentFadeAndSlideAnimation() +{ + Q_D(MContentFadeAndSlideAnimation); + + delete d->snapshotItem; +} + +void MContentFadeAndSlideAnimation::restoreTargetWidgetState() +{} + +void MContentFadeAndSlideAnimation::setTransitionDirection(MAbstractWidgetAnimation::TransitionDirection /*direction*/) +{} + +void MContentFadeAndSlideAnimation::takeContentSnapshot() +{ + Q_D(MContentFadeAndSlideAnimation); + + if (d->contentItem) + d->snapshotItem->updateSnapshot(d->contentItem); +} + +void MContentFadeAndSlideAnimation::setTargetWidget(MWidgetController *targetWidget) +{ + MAbstractWidgetAnimation::setTargetWidget(targetWidget); + + Q_D(MContentFadeAndSlideAnimation); + + d->contentItem = 0; + + if (!targetWidget) + return; + + foreach(QGraphicsItem* item, targetWidget->childItems()) { + if (!item->isWidget()) + continue; + QGraphicsWidget *widget = static_cast(item); + if (widget->objectName() == style()->contentObjectName()) { + d->contentItem = widget; + break; + } + } + +} + +void MContentFadeAndSlideAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) +{ + Q_D(MContentFadeAndSlideAnimation); + + if (!d->contentItem) + return; + + if (oldState == QAbstractAnimation::Stopped && + newState == QAbstractAnimation::Running) + { + d->fadeOut->setStartValue(d->contentItem->opacity()); + d->fadeOut->setEndValue(0.0); + d->fadeOut->setDuration(style()->fadeOutDuration()); + d->fadeOut->setEasingCurve(style()->fadeOutEasingCurve()); + d->fadeOut->setTargetObject(d->snapshotItem); + + QRectF startRect = d->contentItem->boundingRect(); + QRectF finalRect = startRect.translated(style()->slideOutDisplacement()); + QTransform transform = d->contentItem->sceneTransform(); + d->slideOut->setStartValue(transform.mapRect(startRect).topLeft()); + d->slideOut->setEndValue(transform.mapRect(finalRect).topLeft()); + d->slideOut->setDuration(style()->slideOutDuration()); + d->slideOut->setEasingCurve(style()->slideOutEasingCurve()); + d->slideOut->setTargetObject(d->snapshotItem); + + d->delay->setDuration(style()->delay()); + + d->fadeIn->setStartValue(0.0); + d->fadeIn->setEndValue(d->contentItem->opacity()); + d->fadeIn->setDuration(style()->fadeInDuration()); + d->fadeIn->setEasingCurve(style()->fadeInEasingCurve()); + d->fadeIn->setTargetObject(d->contentItem); + + d->slideIn->setStartValue(d->contentItem->pos() + style()->slideInDisplacement()); + d->slideIn->setEndValue(d->contentItem->pos()); + d->slideIn->setDuration(style()->slideInDuration()); + d->slideIn->setEasingCurve(style()->slideInEasingCurve()); + d->slideIn->setTargetObject(d->contentItem); + + d->targetWidget->scene()->addItem(d->snapshotItem); + + // animation is delayed so apply initial values now + d->contentItem->setOpacity(d->fadeIn->startValue().toReal()); + d->contentItem->setPos(d->slideIn->startValue().toPointF()); + + } else if (oldState == QAbstractAnimation::Running && + newState == QAbstractAnimation::Stopped) + { + d->targetWidget->scene()->removeItem(d->snapshotItem); + + // apply final values (for cases when animation was stopped in the middle) + d->contentItem->setOpacity(d->fadeIn->endValue().toReal()); + d->contentItem->setPos(d->slideIn->endValue().toPointF()); + } + + MAbstractWidgetAnimation::updateState(newState, oldState); +} + diff --git a/src/corelib/animation/widget/mcontentfadeandslideanimation.h b/src/corelib/animation/widget/mcontentfadeandslideanimation.h new file mode 100644 index 00000000..f2d5dd16 --- /dev/null +++ b/src/corelib/animation/widget/mcontentfadeandslideanimation.h @@ -0,0 +1,54 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ +#ifndef MCONTENTFADEANDSLIDEANIMATIONMATION_H +#define MCONTENTFADEANDSLIDEANIMATIONMATION_H + +#include "mabstractwidgetanimation.h" +#include "mcontentfadeandslideanimationstyle.h" + +class MContentFadeAndSlideAnimationPrivate; +class MContentFadeAndSlideAnimationStyle; + +//! \internal +class MContentFadeAndSlideAnimation : public MAbstractWidgetAnimation +{ + Q_OBJECT + Q_DECLARE_PRIVATE(MContentFadeAndSlideAnimation) + M_ANIMATION_GROUP(MContentFadeAndSlideAnimationStyle) + +public: + explicit MContentFadeAndSlideAnimation(QObject *parent = 0); + virtual ~MContentFadeAndSlideAnimation(); + + virtual void setTargetWidget(MWidgetController *widget); + +public slots: + void takeContentSnapshot(); + +protected: + //! \reimp + virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); + //! \reimp_end + + virtual void restoreTargetWidgetState(); + virtual void setTransitionDirection(MAbstractWidgetAnimation::TransitionDirection direction); +}; +//! \internal_end + +#endif // MContentFadeAndSlideAnimationmation_H diff --git a/src/corelib/animation/widget/mcontentfadeandslideanimation_p.h b/src/corelib/animation/widget/mcontentfadeandslideanimation_p.h new file mode 100644 index 00000000..a2d37a93 --- /dev/null +++ b/src/corelib/animation/widget/mcontentfadeandslideanimation_p.h @@ -0,0 +1,63 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ + +#ifndef MCONTENTFADEANDSLIDEANIMATION_P_H +#define MCONTENTFADEANDSLIDEANIMATION_P_H + +#include "mabstractwidgetanimation_p.h" + +class MContentFadeAndSlideAnimation; +class QParallelAnimationGroup; +class QSequentialAnimationGroup; +class QPropertyAnimation; +class QPauseAnimation; + +class SnapshotItem : public QGraphicsWidget +{ +public: + void updateSnapshot(QGraphicsWidget* target); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + QPixmap pixmap; +}; + +class MContentFadeAndSlideAnimationPrivate : public MAbstractWidgetAnimationPrivate +{ + Q_DECLARE_PUBLIC(MContentFadeAndSlideAnimation) +public: + MContentFadeAndSlideAnimationPrivate(); + + void init(); + + QPointer snapshotItem; + QGraphicsWidget* contentItem; + + QParallelAnimationGroup* previous; + QPropertyAnimation* fadeOut; + QPropertyAnimation* slideOut; + QParallelAnimationGroup* current; + QPropertyAnimation* fadeIn; + QPropertyAnimation* slideIn; + QSequentialAnimationGroup* currentWithDelay; + QPauseAnimation* delay; +}; + +#endif diff --git a/src/corelib/animation/widget/widget.pri b/src/corelib/animation/widget/widget.pri index 7f21a2ba..f6b2fe21 100644 --- a/src/corelib/animation/widget/widget.pri +++ b/src/corelib/animation/widget/widget.pri @@ -13,6 +13,7 @@ PUBLIC_HEADERS += \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetslideanimation.h \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetzoomanimation.h \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetrectangularclipanimation.h \ + $$ANIMATIONS_WIDGET_SRC_DIR/mcontentfadeandslideanimation.h \ PRIVATE_HEADERS += \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetfadeanimation_p.h \ @@ -20,6 +21,7 @@ PRIVATE_HEADERS += \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetslideanimation_p.h \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetzoomanimation_p.h \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetrectangularclipanimation_p.h \ + $$ANIMATIONS_WIDGET_SRC_DIR/mcontentfadeandslideanimation_p.h \ SOURCES += \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetfadeanimation.cpp \ @@ -27,3 +29,4 @@ SOURCES += \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetslideanimation.cpp \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetzoomanimation.cpp \ $$ANIMATIONS_WIDGET_SRC_DIR/mwidgetrectangularclipanimation.cpp \ + $$ANIMATIONS_WIDGET_SRC_DIR/mcontentfadeandslideanimation.cpp \ diff --git a/src/corelib/style/mcontentfadeandslideanimationstyle.h b/src/corelib/style/mcontentfadeandslideanimationstyle.h new file mode 100644 index 00000000..77399fe1 --- /dev/null +++ b/src/corelib/style/mcontentfadeandslideanimationstyle.h @@ -0,0 +1,57 @@ +/*************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (directui@nokia.com) +** +** This file is part of libmeegotouch. +** +** If you have questions regarding the use of this file, please contact +** Nokia at directui@nokia.com. +** +** This library is free software; you can redistribute it and/or +** modify it under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation +** and appearing in the file LICENSE.LGPL included in the packaging +** of this file. +** +****************************************************************************/ +#ifndef MCONTENTFADEANDSLIDEANIMATIONSTYLE_H +#define MCONTENTFADEANDSLIDEANIMATIONSTYLE_H + +#include "mabstractwidgetanimationstyle.h" +#include +#include + +//! \internal +class M_CORE_EXPORT MContentFadeAndSlideAnimationStyle : public MAbstractWidgetAnimationStyle +{ + Q_OBJECT + M_STYLE_INTERNAL(MContentFadeAndSlideAnimationStyle) + + M_STYLE_ATTRIBUTE(QString, contentObjectName, ContentObjectName) + + M_STYLE_ATTRIBUTE(int, fadeOutDuration, fadeOutDuration) + M_STYLE_ATTRIBUTE(QEasingCurve, fadeOutEasingCurve, FadeOutEasingCurve) + + M_STYLE_ATTRIBUTE(QPointF, slideOutDisplacement, SlideOutDisplacement) + M_STYLE_ATTRIBUTE(int, slideOutDuration, SlideOutDuration) + M_STYLE_ATTRIBUTE(QEasingCurve, slideOutEasingCurve, SlideOutEasingCurve) + + M_STYLE_ATTRIBUTE(int, delay, Delay) + + M_STYLE_ATTRIBUTE(int, fadeInDuration, FadeInDuration) + M_STYLE_ATTRIBUTE(QEasingCurve, fadeInEasingCurve, FadeInEasingCurve) + + M_STYLE_ATTRIBUTE(QPointF, slideInDisplacement, SlideInDisplacement) + M_STYLE_ATTRIBUTE(int, slideInDuration, SlideInDuration) + M_STYLE_ATTRIBUTE(QEasingCurve, slideInEasingCurve, SlideInEasingCurve) +}; + +class MContentFadeAndSlideAnimationStyleContainer : public MAbstractWidgetAnimationStyleContainer +{ + M_STYLE_CONTAINER_INTERNAL(MContentFadeAndSlideAnimationStyle) +}; +//! \internal_end + +#endif // MContentFadeAndSlideAnimationmationSTYLE_H diff --git a/src/corelib/style/style.pri b/src/corelib/style/style.pri index 1916b61f..4e10c747 100644 --- a/src/corelib/style/style.pri +++ b/src/corelib/style/style.pri @@ -43,6 +43,7 @@ STYLE_HEADERS += \ $$STYLE_SRC_DIR/mwidgetrectangularclipanimationstyle.h \ $$STYLE_SRC_DIR/mrelocatorstyle.h \ $$STYLE_SRC_DIR/mwindowstyle.h \ + $$STYLE_SRC_DIR/mcontentfadeandslideanimationstyle.h \ PUBLIC_HEADERS += \ $$STYLE_HEADERS \ diff --git a/src/corelib/widgets/mapplicationwindow.cpp b/src/corelib/widgets/mapplicationwindow.cpp index 0eda5bc3..178e6051 100644 --- a/src/corelib/widgets/mapplicationwindow.cpp +++ b/src/corelib/widgets/mapplicationwindow.cpp @@ -42,6 +42,7 @@ #include "mstatusbar.h" #include "mdeviceprofile.h" #include "mcomponentdata.h" +#include "mcontentfadeandslideanimation.h" #include #include @@ -97,6 +98,7 @@ MApplicationWindowPrivate::MApplicationWindowPrivate() , showingNavigationBar(false) , showingDockWidget(false) , navigationBarPressed(false) + , navigationBarAnimation(0) , styleContainer(0) { if(MDeviceProfile::instance()->showStatusbar()) { @@ -117,7 +119,7 @@ MApplicationWindowPrivate::~MApplicationWindowPrivate() delete toolBar; toolBar = 0; } - + if (menu) { delete menu; menu = 0; @@ -207,6 +209,12 @@ void MApplicationWindowPrivate::init() sceneManager->appearSceneWindowNow(navigationBar); sceneManager->appearSceneWindowNow(homeButtonPanel); + navigationBarAnimation = new MContentFadeAndSlideAnimation(q); + navigationBarAnimation->setTargetWidget(navigationBar); + // when pageHistoryChange is emitted it's last chance to grab previous navigationBar contents + q->connect(q->sceneManager(), SIGNAL(pageHistoryChanged()), + navigationBarAnimation, SLOT(takeContentSnapshot())); + // Initialize escape button to close mode. navigationBar->setEscapeButtonMode(MNavigationBarModel::EscapeButtonClose); QObject::connect(navigationBar, SIGNAL(closeButtonClicked()), q, SLOT(close())); @@ -865,6 +873,12 @@ void MApplicationWindowPrivate::applicationPageAppearEvent(MSceneWindowEvent *ev connectPage(pageFromEvent); _q_updatePageExposedContentRect(); + // very fast user can switch page before animation finishes + navigationBarAnimation->stop(); + + if (event->animatedTransition()) + navigationBarAnimation->start(); + #ifdef Q_WS_X11 if (pageFromEvent && isChained && sceneManager) { bool isFirstPage = sceneManager->pageHistory().isEmpty(); diff --git a/src/corelib/widgets/mapplicationwindow_p.h b/src/corelib/widgets/mapplicationwindow_p.h index e3e9d885..106a5b63 100644 --- a/src/corelib/widgets/mapplicationwindow_p.h +++ b/src/corelib/widgets/mapplicationwindow_p.h @@ -46,6 +46,7 @@ class MApplicationPageInfo; class MApplicationWindow; class MSceneWindowEvent; class QActionEvent; +class MContentFadeAndSlideAnimation; class MApplicationWindowPrivate : public MWindowPrivate { @@ -86,6 +87,8 @@ public: bool navigationBarPressed; + MContentFadeAndSlideAnimation* navigationBarAnimation; + void manageActions(); void distributeAction(QAction *action, QAction *before); void refreshArrowIconVisibility(); diff --git a/src/views/mnavigationbarview.cpp b/src/views/mnavigationbarview.cpp index c0ed0476..7ab20055 100644 --- a/src/views/mnavigationbarview.cpp +++ b/src/views/mnavigationbarview.cpp @@ -39,7 +39,8 @@ // -------------------------------------------------------------------------- MNavigationBarViewPrivate::MNavigationBarViewPrivate() - : layout(0), + : content(0), + layout(0), menuToolbarEscapePolicy(0), escapeToolbarMenuPolicy(0), escapeToolbarPolicy(0), @@ -92,9 +93,15 @@ void MNavigationBarViewPrivate::init() backButton = new MButton(escapeButtonSlot); backButton->setViewType("icon"); + QGraphicsLinearLayout* contentLayout = new QGraphicsLinearLayout(controller); + contentLayout->setContentsMargins(0, 0, 0, 0); + content = new QGraphicsWidget; + content->setObjectName("ContentToAnimate"); + contentLayout->addItem(content); + layout = new MLayout; layout->setContentsMargins(0, 0, 0, 0); - controller->setLayout(layout); + content->setLayout(layout); toolBarSlot = new QGraphicsWidget(controller); toolBarSlot->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -458,4 +465,4 @@ void MNavigationBarView::drawBackground(QPainter *painter, const QStyleOptionGra M_REGISTER_VIEW_NEW(MNavigationBarView, MNavigationBar) -#include "moc_mnavigationbarview.cpp" \ No newline at end of file +#include "moc_mnavigationbarview.cpp" diff --git a/src/views/mnavigationbarview_p.h b/src/views/mnavigationbarview_p.h index c1f48ca8..10302eae 100644 --- a/src/views/mnavigationbarview_p.h +++ b/src/views/mnavigationbarview_p.h @@ -59,6 +59,8 @@ public: void updateToolBarAlignment(); void setCustomContent(QGraphicsWidget *customContent); + QGraphicsWidget* content; + MLayout *layout; // parts of policy name describe which components are visible and in what order -- cgit v1.2.3