diff --git a/clients/aurorae/src/aurorae.cpp b/clients/aurorae/src/aurorae.cpp index 2e98b7bf48..2e4997e8a1 100644 --- a/clients/aurorae/src/aurorae.cpp +++ b/clients/aurorae/src/aurorae.cpp @@ -278,6 +278,19 @@ void AuroraeButton::paintEvent(QPaintEvent *event) } else { iconPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState); } + AuroraeClient *deco = dynamic_cast(decoration()); + if (deco && deco->isAnimating()) { + // animation + QPixmap oldPix = icon.pixmap(size); + if (!active) { + if (underMouse()) { + oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::ActiveState); + } + } else { + oldPix = effect->apply(iconPix, KIconLoader::Desktop, KIconLoader::DisabledState); + } + iconPix = Plasma::PaintUtils::transition(oldPix, iconPix, deco->animationProgress()); + } painter.drawPixmap(0, 0, iconPix); return; } @@ -450,7 +463,28 @@ void AuroraeButton::paintButton(QPainter &painter, Plasma::FrameSvg *frame, Butt target, m_animationProgress); painter.drawPixmap(rect(), result); } else { - frame->paintFrame(&painter); + bool animation = false; + AuroraeClient *deco = dynamic_cast(decoration()); + if (deco && deco->isAnimating()) { + animationPrefix = prefix; + if (prefix.endsWith("-inactive")) { + animationPrefix.remove("-inactive"); + } else { + animationPrefix = animationPrefix + "-inactive"; + } + if (frame->hasElementPrefix(animationPrefix)) { + animation = true; + QPixmap target = frame->framePixmap(); + frame->setElementPrefix(animationPrefix); + frame->resizeFrame(size()); + QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(), + target, deco->animationProgress()); + painter.drawPixmap(rect(), result); + } + } + if (!animation) { + frame->paintFrame(&painter); + } } } @@ -461,6 +495,7 @@ void AuroraeButton::paintButton(QPainter &painter, Plasma::FrameSvg *frame, Butt AuroraeClient::AuroraeClient(KDecorationBridge *bridge, KDecorationFactory *factory) : KCommonDecorationUnstable(bridge, factory) { + connect(Plasma::Animator::self(), SIGNAL(customAnimationFinished(int)), this, SLOT(animationFinished(int))); } AuroraeClient::~AuroraeClient() @@ -655,6 +690,7 @@ void AuroraeClient::paintEvent(QPaintEvent *event) !options()->moveResizeMaximizedWindows(); QPainter painter(widget()); + painter.setRenderHint(QPainter::Antialiasing); painter.setCompositionMode(QPainter::CompositionMode_Source); const ThemeConfig &conf = AuroraeFactory::instance()->themeConfig(); @@ -718,15 +754,58 @@ void AuroraeClient::paintEvent(QPaintEvent *event) } } frame->resizeFrame(rect.size()); - frame->paintFrame(&painter, rect, sourceRect); - painter.setFont(options()->font(isActive())); + // animation + if (m_animationId != 0 && frame->hasElementPrefix("decoration-inactive")) { + QPixmap target = frame->framePixmap(); + frame->setElementPrefix("decoration-inactive"); + if (!isActive()) { + frame->setElementPrefix("decoration"); + } + if (!compositingActive() && frame->hasElementPrefix("decoration-opaque-inactive")) { + frame->setElementPrefix("decoration-opaque-inactive"); + if (!isActive()) { + frame->setElementPrefix("decoration-opaque"); + } + } + frame->resizeFrame(rect.size()); + QPixmap result = Plasma::PaintUtils::transition(frame->framePixmap(), + target, m_animationProgress); + painter.drawPixmap(rect.toRect(), result); + } else { + frame->paintFrame(&painter, rect, sourceRect); + } + + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + if (m_animationId != 0) { + QPixmap result; + if (isActive()) { + result = Plasma::PaintUtils::transition(m_inactiveText, m_activeText, m_animationProgress); + } else { + result = Plasma::PaintUtils::transition(m_activeText, m_inactiveText, m_animationProgress); + } + painter.drawPixmap(titleRect(), result); + } else { + if (isActive()) { + painter.drawPixmap(titleRect(), m_activeText); + } else { + painter.drawPixmap(titleRect(), m_inactiveText); + } + } +} + +void AuroraeClient::generateTextPixmap(QPixmap& pixmap, bool active) +{ + QPainter painter(&pixmap); + pixmap.fill(Qt::transparent); + const ThemeConfig &conf = AuroraeFactory::instance()->themeConfig(); + painter.setFont(options()->font(active)); if (conf.useTextShadow()) { // shadow code is inspired by Qt FAQ: How can I draw shadows behind text? // see http://www.qtsoftware.com/developer/faqs/faq.2007-07-27.3052836051 const ThemeConfig &conf = AuroraeFactory::instance()->themeConfig(); painter.save(); - if (isActive()) { + if (active) { painter.setPen(conf.activeTextShadowColor()); } else { @@ -735,31 +814,39 @@ void AuroraeClient::paintEvent(QPaintEvent *event) int dx = conf.textShadowOffsetX(); int dy = conf.textShadowOffsetY(); painter.setOpacity(0.5); - painter.drawText(titleRect().translated(dx, dy), + painter.drawText(pixmap.rect().translated(dx, dy), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); painter.setOpacity(0.2); - painter.drawText(titleRect().translated(dx+1, dy), + painter.drawText(pixmap.rect().translated(dx+1, dy), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); - painter.drawText(titleRect().translated(dx-1, dy), + painter.drawText(pixmap.rect().translated(dx-1, dy), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); - painter.drawText(titleRect().translated(dx, dy+1), + painter.drawText(pixmap.rect().translated(dx, dy+1), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); - painter.drawText(titleRect().translated(dx, dy-1), + painter.drawText(pixmap.rect().translated(dx, dy-1), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); painter.restore(); } - if (isActive()) { + if (active) { painter.setPen(conf.activeTextColor()); } else { painter.setPen(conf.inactiveTextColor()); } - painter.drawText(titleRect(), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, + painter.drawText(pixmap.rect(), conf.alignment() | conf.verticalAlignment() | Qt::TextSingleLine, caption()); + painter.end(); +} + +void AuroraeClient::captionChange() +{ + generateTextPixmap(m_activeText, true); + generateTextPixmap(m_inactiveText, false); + KCommonDecoration::captionChange(); } void AuroraeClient::updateWindowShape() @@ -791,6 +878,46 @@ void AuroraeClient::updateWindowShape() setMask(mask); } +void AuroraeClient::activeChange() +{ + if (m_animationId != 0) { + Plasma::Animator::self()->stopCustomAnimation(m_animationId); + } + m_animationProgress = 0.0; + int time = AuroraeFactory::instance()->themeConfig().animationTime(); + if (time != 0) { + m_animationId = Plasma::Animator::self()->customAnimation(40 / (1000.0 / qreal(time)), + time, Plasma::Animator::EaseInOutCurve, this, "animationUpdate"); + } + KCommonDecoration::activeChange(); +} + +void AuroraeClient::animationUpdate(qreal progress, int id) +{ + if (m_animationId == id) { + m_animationProgress = progress; + widget()->update(); + } +} + +void AuroraeClient::animationFinished(int id) +{ + if (m_animationId == id) { + m_animationId = 0; + widget()->update(); + } +} + +void AuroraeClient::resize(const QSize& s) +{ + KCommonDecoration::resize(s); + m_activeText = QPixmap(titleRect().size()); + m_activeText.fill(Qt::transparent); + m_inactiveText = QPixmap(titleRect().size()); + m_inactiveText.fill(Qt::transparent); + captionChange(); +} + } // namespace Aurorae extern "C" diff --git a/clients/aurorae/src/aurorae.h b/clients/aurorae/src/aurorae.h index 76e94014e7..10fb682899 100644 --- a/clients/aurorae/src/aurorae.h +++ b/clients/aurorae/src/aurorae.h @@ -122,11 +122,28 @@ public: const KCommonDecorationButton * = 0) const; virtual KCommonDecorationButton *createButton(ButtonType type); virtual void updateWindowShape(); + virtual void activeChange(); + virtual void captionChange(); + virtual void resize(const QSize& s); + + bool isAnimating() const { return m_animationId != 0; } + qreal animationProgress() const { return m_animationProgress; } + +public slots: + void animationUpdate(qreal progress, int id); + void animationFinished(int id); protected: void reset(unsigned long changed); void paintEvent(QPaintEvent *event); +private: + void generateTextPixmap(QPixmap& pixmap, bool active); + int m_animationId; + qreal m_animationProgress; + QPixmap m_activeText; + QPixmap m_inactiveText; + }; } diff --git a/clients/aurorae/theme-description b/clients/aurorae/theme-description index 796b94093e..ff080d60c6 100644 --- a/clients/aurorae/theme-description +++ b/clients/aurorae/theme-description @@ -86,7 +86,7 @@ The following section shows the possible options with their default values. [General] TitleAlignment=Left # vorizontal alignment of window title TitleVerticalAlignment=Center # vertical alignment of window title -Animation=0 # animation duration in msec when hovering a button +Animation=0 # animation duration in msec when hovering a button and on active/inactive change ActiveTextColor=0,0,0,255 # title text color of active window InactiveTextColor=0,0,0,255 # title text color of inactive window UseTextShadow=false # Draw Shadow behind title text