plasma-framework/animations/pulser.cpp
Adenilson Cavalcanti Da Silva c18c6188e3 Workaround for deforming animated widget if a new pulse event
was triggered while the animation was running and *before*
it was over.

For while, it will just ignore the geometry calculus and return
(but ideally it should listen for the event emited when the animation
is over and then recalculate the geometries).


svn path=/trunk/KDE/kdelibs/; revision=1039630
2009-10-24 03:04:17 +00:00

185 lines
5.3 KiB
C++

/* Copyright (C) 2009 Adenilson Cavalcanti <cavalcantii@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* TODO:
* - fix centering of pulsed shadow object
*/
#include "pulser_p.h"
#include <QAbstractAnimation>
#include <QDebug>
#include <QEvent>
#include <QGraphicsWidget>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
#include <kdebug.h>
namespace Plasma
{
class PulseAnimationPrivate
{
public :
PulseAnimationPrivate()
: animation(0),
under(0),
pulseGeometry(0),
zvalue(0),
mscale(0),
opacityAnimation(0),
geometryAnimation(0),
scaleAnimation(0)
{}
QAbstractAnimation *animation;
QGraphicsWidget *under;
/* FIXME: clean up this guy */
QRectF *pulseGeometry;
qreal zvalue, mscale, mopacity;
QPropertyAnimation *opacityAnimation;
QPropertyAnimation *geometryAnimation;
QPropertyAnimation *scaleAnimation;
};
PulseAnimation::PulseAnimation(): d(new PulseAnimationPrivate)
{
}
PulseAnimation::~PulseAnimation()
{
//XXX: current plasma::Animation model will delete all animation objects
// delete animation;
// delete pulseGeometry;
delete d;
}
void PulseAnimation::setCopy(QGraphicsWidget *copy)
{
QGraphicsWidget *target = widgetToAnimate();
d->under = copy;
if (d->under == target) {
d->mopacity = d->under->opacity();
} else {
d->under->setParentItem(target);
d->mopacity = 0;
}
d->zvalue = target->zValue();
--d->zvalue;
d->under->setOpacity(0);
d->under->setZValue(d->zvalue);
d->mscale = d->under->scale();
}
void PulseAnimation::resetPulser()
{
d->under->setGeometry(*d->pulseGeometry);
d->under->setOpacity(d->mopacity);
d->under->setZValue(d->zvalue);
d->under->setScale(d->mscale);
}
void PulseAnimation::createAnimation(qreal duration, qreal scale)
{
bool dirty = false;
QGraphicsWidget *target = widgetToAnimate();
/* Fallback to parent widget if we don't have one 'shadow' widget */
if (!d->under) {
setCopy(target);
} else if (d->under != target) {
delete d->under;
d->under = new QGraphicsWidget(target);
setCopy(d->under);
}
QParallelAnimationGroup *anim = dynamic_cast<QParallelAnimationGroup* >(animation());
if (!anim) {
d->pulseGeometry = new QRectF(d->under->geometry());
QParallelAnimationGroup *group = new QParallelAnimationGroup(this);
d->opacityAnimation = new QPropertyAnimation(d->under, "opacity");
d->opacityAnimation->setDuration(duration);
d->opacityAnimation->setEndValue(0);
group->addAnimation(d->opacityAnimation);
/* TODO: move this to a function */
d->geometryAnimation = new QPropertyAnimation(d->under, "geometry");
d->geometryAnimation->setDuration(duration);
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
group->addAnimation(d->geometryAnimation);
d->scaleAnimation = new QPropertyAnimation(d->under, "scale");
d->scaleAnimation->setDuration(duration);
d->scaleAnimation->setEndValue(scale);
/* The group takes ownership of all animations */
group->addAnimation(d->scaleAnimation);
d->animation = group;
setAnimation(d->animation);
dirty = true;
} else {
/* Stop the animation or the widget will be deformed.
*/
QAbstractAnimation::State temp = anim->state();
if (temp == QAbstractAnimation::Running) {
anim->stop();
/* TODO: will need to watch stateChanged signal
* and *then* reset the geometry
*/
} else {
/* TODO: move this to a function */
*(d->pulseGeometry) = d->under->geometry();
d->opacityAnimation->setEndValue(0);
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
}
}
if (dirty) {
//This makes sure that if there is *not* a shadow widget, the
//parent widget will still remain visible
connect(d->animation, SIGNAL(finished()), this, SLOT(resetPulser()));
}
}
QAbstractAnimation* PulseAnimation::render(QObject* parent)
{
Q_UNUSED(parent)
createAnimation(duration());
d->under->setOpacity(1);
return d->animation;
}
} //namespace Plasma