Added animated button glow.

svn path=/trunk/KDE/kdebase/workspace/; revision=1024489
This commit is contained in:
Hugo Pereira Da Costa 2009-09-16 17:09:33 +00:00
parent 24270ef9f3
commit e679d07b93
5 changed files with 229 additions and 13 deletions

View file

@ -14,6 +14,7 @@ set(kwin_oxygen_SRCS
oxygenexceptionlist.cpp
oxygenshadowconfiguration.cpp
oxygensizegrip.cpp
oxygentimeline.cpp
x11util.cpp
)

View file

@ -38,6 +38,7 @@
#include <KColorUtils>
#include <KColorScheme>
#include <kcommondecoration.h>
#include <KDebug>
namespace Oxygen
{
@ -48,7 +49,8 @@ namespace Oxygen
client_(parent),
helper_( parent.helper() ),
type_(type),
colorCacheInvalid_(true)
colorCacheInvalid_(true),
timeLine_( 200, this )
{
setAutoFillBackground(false);
setAttribute(Qt::WA_NoSystemBackground);
@ -60,6 +62,12 @@ namespace Oxygen
setCursor(Qt::ArrowCursor);
setToolTip(tip);
timeLine_.setFrameRange( 0, 1000 );
timeLine_.setCurveShape( QTimeLine::EaseInOutCurve );
connect( &timeLine_, SIGNAL( currentIndexChanged( int ) ), SLOT( repaint() ) );
connect( &timeLine_, SIGNAL( finished() ), SLOT( repaint() ) );
}
//_______________________________________________
@ -103,6 +111,9 @@ namespace Oxygen
{
KCommonDecorationButton::enterEvent(e);
if (status_ != Oxygen::Pressed) status_ = Oxygen::Hovered;
if( timeLine_.state() != OxygenTimeLine::NotRunning ) timeLine_.stop();
timeLine_.setDirection( OxygenTimeLine::Forward );
timeLine_.start();
update();
}
@ -111,7 +122,13 @@ namespace Oxygen
{
KCommonDecorationButton::leaveEvent(e);
status_ = Oxygen::Normal;
if( timeLine_.state() != OxygenTimeLine::NotRunning ) timeLine_.stop();
timeLine_.setDirection( OxygenTimeLine::Backward );
timeLine_.start();
update();
}
//___________________________________________________
@ -176,12 +193,17 @@ namespace Oxygen
return;
}
// calculate color depending on timeline state
color = buttonDetailColor(palette);
if(status_ == Oxygen::Hovered || status_ == Oxygen::Pressed)
QColor glow = (type_ == ButtonClose) ?
KColorScheme(palette.currentColorGroup()).foreground(KColorScheme::NegativeText).color():
KColorScheme(palette.currentColorGroup()).decoration(KColorScheme::HoverColor).color();
if( timeLine_.state() == OxygenTimeLine::Running )
{
if(type_ == ButtonClose) color = KColorScheme(palette.currentColorGroup()).foreground(KColorScheme::NegativeText).color();
else color = KColorScheme(palette.currentColorGroup()).decoration(KColorScheme::HoverColor).color();
}
qreal ratio( qreal( timeLine_.currentIndex() )/qreal( timeLine_.maxIndex() ) );
color = KColorUtils::mix( color, glow, ratio );
} else if( status_ == Oxygen::Hovered ) color = glow;
// translate buttons up if window maximized
if(client_.isMaximized())
@ -194,8 +216,15 @@ namespace Oxygen
painter.drawPixmap(0, 0, helper_.windecoButton(bt, status_ == Oxygen::Pressed, (21.0*client_.configuration().buttonSize())/22 ) );
// draw glow on hover
if( status_ == Oxygen::Hovered )
{ painter.drawPixmap(0, 0, helper_.windecoButtonGlow(color, (21.0*client_.configuration().buttonSize())/22)); }
if( status_ == Oxygen::Hovered || timeLine_.state() == OxygenTimeLine::Running )
{
qreal ratio( qreal( timeLine_.currentIndex() )/qreal( timeLine_.maxIndex() ) );
painter.save();
painter.setOpacity( ratio );
painter.drawPixmap(0, 0, helper_.windecoButtonGlow(glow, (21.0*client_.configuration().buttonSize())/22));
painter.restore();
}
// draw button icon
if (client_.isActive())

View file

@ -32,6 +32,7 @@
#include "oxygen.h"
#include "oxygenclient.h"
#include "oxygentimeline.h"
namespace Oxygen
{
@ -60,10 +61,6 @@ namespace Oxygen
//! destructor
QSize sizeHint() const;
//! last button mouse
// int lastMousePress() const
// {return lastmouse_;}
//! reset
void reset(long unsigned int)
{repaint();}
@ -111,10 +108,12 @@ namespace Oxygen
//! button status
ButtonState status_;
//! last button mouse pressed
int lastmouse_;
bool colorCacheInvalid_;
QColor cachedButtonDetailColor_;
//! timeline used for smooth transitions
OxygenTimeLine timeLine_;
};
} //namespace Oxygen

View file

@ -0,0 +1,94 @@
//////////////////////////////////////////////////////////////////////////////
// OxygenTimeLine.h
// derive from QTimeLine and is used to perform smooth transitions
// -------------------
//
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////////
#include "oxygentimeline.h"
#include "oxygentimeline.moc"
#include <cassert>
#include <KDebug>
namespace Oxygen
{
//______________________________________________________
OxygenTimeLine::OxygenTimeLine( int duration, QObject* parent ):
QTimeLine( duration, parent ),
direction_( Forward ),
currentIndex_( 0 ),
maxIndex_( 255 ),
lastFrame_( 0 )
{
// connections
connect( this, SIGNAL( frameChanged( int ) ), SLOT( updateCurrentIndex( int ) ) );
}
//______________________________________________________
void OxygenTimeLine::start( void )
{
assert( state() == NotRunning );
lastFrame_ = 0;
QTimeLine::start();
}
//______________________________________________________
void OxygenTimeLine::updateCurrentIndex( int currentFrame )
{
// check interval
if( currentFrame <= lastFrame_ ) lastFrame_ = 0;
// calculate step
int step = (maxIndex()*( currentFrame - lastFrame_ ))/endFrame();
if( direction_ == Backward ) step *= -1;
// update lastFrame
lastFrame_ = currentFrame;
// check end conditions
if( currentIndex_ + step <= 0 )
{
currentIndex_ = 0;
emit currentIndexChanged( currentIndex_ );
stop();
} else if( currentIndex_ + step >= maxIndex_ ) {
currentIndex_ = maxIndex_;
emit currentIndexChanged( currentIndex_ );
stop();
} else {
currentIndex_ += step;
emit currentIndexChanged( currentIndex_ );
}
}
}

View file

@ -0,0 +1,93 @@
#ifndef oxygentimeline_h
#define oxygentimeline_h
//////////////////////////////////////////////////////////////////////////////
// OxygenTimeLine.h
// derive from QTimeLine and is used to perform smooth transitions
// -------------------
//
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//////////////////////////////////////////////////////////////////////////////
#include <QTimeLine>
namespace Oxygen
{
class OxygenTimeLine: public QTimeLine
{
Q_OBJECT
public:
//! constructor
OxygenTimeLine( int duration, QObject* parent );
//! max number of Index
void setMaxIndex( int value )
{ maxIndex_ = value; }
//! max number of Index
int maxIndex( void ) const
{ return maxIndex_; }
//! current Index
int currentIndex( void ) const
{ return currentIndex_; }
//! direction used to update Index
void setDirection( QTimeLine::Direction value )
{ direction_ = value; }
//! start
void start( void );
signals:
//! emitted whenever the current Index changed
void currentIndexChanged( int );
protected slots:
//! connected to timeLine frameChanged
void updateCurrentIndex( int );
private:
//! direction
Direction direction_;
//! current Index
int currentIndex_;
//! max Index
int maxIndex_;
//! frame at last update
int lastFrame_;
};
}
#endif