From e679d07b93109a17d336ce6d29262dadf876ecdf Mon Sep 17 00:00:00 2001 From: Hugo Pereira Da Costa Date: Wed, 16 Sep 2009 17:09:33 +0000 Subject: [PATCH] Added animated button glow. svn path=/trunk/KDE/kdebase/workspace/; revision=1024489 --- clients/oxygen/CMakeLists.txt | 1 + clients/oxygen/oxygenbutton.cpp | 43 +++++++++++--- clients/oxygen/oxygenbutton.h | 11 ++-- clients/oxygen/oxygentimeline.cpp | 94 +++++++++++++++++++++++++++++++ clients/oxygen/oxygentimeline.h | 93 ++++++++++++++++++++++++++++++ 5 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 clients/oxygen/oxygentimeline.cpp create mode 100644 clients/oxygen/oxygentimeline.h diff --git a/clients/oxygen/CMakeLists.txt b/clients/oxygen/CMakeLists.txt index abdb3eb6d5..9fca512779 100644 --- a/clients/oxygen/CMakeLists.txt +++ b/clients/oxygen/CMakeLists.txt @@ -14,6 +14,7 @@ set(kwin_oxygen_SRCS oxygenexceptionlist.cpp oxygenshadowconfiguration.cpp oxygensizegrip.cpp + oxygentimeline.cpp x11util.cpp ) diff --git a/clients/oxygen/oxygenbutton.cpp b/clients/oxygen/oxygenbutton.cpp index 44684f8858..0b150e05f6 100644 --- a/clients/oxygen/oxygenbutton.cpp +++ b/clients/oxygen/oxygenbutton.cpp @@ -38,6 +38,7 @@ #include #include #include +#include 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()) diff --git a/clients/oxygen/oxygenbutton.h b/clients/oxygen/oxygenbutton.h index 862d9aa4a3..f8a4e3049a 100644 --- a/clients/oxygen/oxygenbutton.h +++ b/clients/oxygen/oxygenbutton.h @@ -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 diff --git a/clients/oxygen/oxygentimeline.cpp b/clients/oxygen/oxygentimeline.cpp new file mode 100644 index 0000000000..fa25c8dd4f --- /dev/null +++ b/clients/oxygen/oxygentimeline.cpp @@ -0,0 +1,94 @@ + +////////////////////////////////////////////////////////////////////////////// +// OxygenTimeLine.h +// derive from QTimeLine and is used to perform smooth transitions +// ------------------- +// +// Copyright (c) 2009 Hugo Pereira Da Costa +// +// 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 +#include + +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_ ); + } + + } + +} diff --git a/clients/oxygen/oxygentimeline.h b/clients/oxygen/oxygentimeline.h new file mode 100644 index 0000000000..bb3bb859eb --- /dev/null +++ b/clients/oxygen/oxygentimeline.h @@ -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 +// +// 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 + +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