From e26538e368f2b94ae618019beb6b605a931f834d Mon Sep 17 00:00:00 2001 From: Hugo Pereira Da Costa Date: Thu, 15 Oct 2009 16:03:30 +0000 Subject: [PATCH] port design changes from tabbing branch to trunk: new title outline design; simplification of layout metrics; proper handling of text ellision; simplification of shadow cache; addition of to local button types. In oxygen.h also temporarily added missing enumeration to ease compilation against kde4.3 svn path=/trunk/KDE/kdebase/workspace/; revision=1035658 --- clients/oxygen/oxygen.h | 22 +- clients/oxygen/oxygenbutton.cpp | 78 +++---- clients/oxygen/oxygenbutton.h | 26 +-- clients/oxygen/oxygenclient.cpp | 334 ++++++++++++--------------- clients/oxygen/oxygenclient.h | 68 +++--- clients/oxygen/oxygenshadowcache.cpp | 58 +---- clients/oxygen/oxygenshadowcache.h | 39 ++-- 7 files changed, 254 insertions(+), 371 deletions(-) diff --git a/clients/oxygen/oxygen.h b/clients/oxygen/oxygen.h index 52433f66e1..b618ac1c44 100644 --- a/clients/oxygen/oxygen.h +++ b/clients/oxygen/oxygen.h @@ -54,7 +54,15 @@ namespace Oxygen ButtonAbove, ButtonBelow, ButtonShade, - ButtonTypeCount + ButtonTypeCount, + + // Close only one tab + ButtonItemClose=100, + + // shows the window menu for one tab + ButtonItemMenu + + }; Q_DECLARE_FLAGS(ButtonTypes, ButtonType) @@ -64,12 +72,6 @@ namespace Oxygen //! maximum index/frame used for animations maxAnimationIndex = 256, - /*! - If non zero, this possibly allow one to have an additional space - around window that is clickable although it is part of the shadow - */ - EXTENDED_HITAREA = 0, - //! this is the top title bar edge TFRAMESIZE = 3, @@ -80,6 +82,10 @@ namespace Oxygen HFRAMESIZE = 4 }; + #if !KDE_IS_VERSION(4,3,90) + enum{ SettingCompositing = 1 << 6 }; + #endif + //! window decoration factory class OxygenFactory: public QObject, public KDecorationFactoryUnstable { @@ -129,7 +135,7 @@ namespace Oxygen bool readConfig(); //! default configuration - OxygenConfiguration defaultConfiguration( void ) + const OxygenConfiguration& defaultConfiguration( void ) { return defaultConfiguration_; } //! initialization diff --git a/clients/oxygen/oxygenbutton.cpp b/clients/oxygen/oxygenbutton.cpp index cc8c43fe1d..e334b46cc0 100644 --- a/clients/oxygen/oxygenbutton.cpp +++ b/clients/oxygen/oxygenbutton.cpp @@ -46,10 +46,8 @@ namespace Oxygen OxygenButton::OxygenButton( OxygenClient &parent, const QString& tip, - ButtonType type, - RenderFlags flags): + ButtonType type): KCommonDecorationButton((::ButtonType)type, &parent), - renderFlags_( flags ), client_(parent), helper_( parent.helper() ), type_(type), @@ -95,16 +93,13 @@ namespace Oxygen if( active ) return palette.color(QPalette::Active, QPalette::ButtonText); else { - if( !cachedButtonDetailColor_.isValid() ) - { - QColor ab = palette.color(QPalette::Active, QPalette::Button); - QColor af = palette.color(QPalette::Active, QPalette::ButtonText); - QColor nb = palette.color(QPalette::Inactive, QPalette::Button); - QColor nf = palette.color(QPalette::Inactive, QPalette::ButtonText); - cachedButtonDetailColor_ = reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); - } + // todo: re-implement caching + QColor ab = palette.color(QPalette::Active, QPalette::Button); + QColor af = palette.color(QPalette::Active, QPalette::ButtonText); + QColor nb = palette.color(QPalette::Inactive, QPalette::Button); + QColor nf = palette.color(QPalette::Inactive, QPalette::ButtonText); + return reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); - return cachedButtonDetailColor_; } } @@ -183,14 +178,11 @@ namespace Oxygen QColor color = palette.window().color(); // window background - if( renderFlags_ & Background ) + if( type_ != ButtonItemClose && type_ != ButtonItemMenu ) { client_.renderWindowBackground( &painter, rect(), this, palette ); - - // window border - if( client_.drawTitleOutline() ) - { client_.renderWindowBorder( &painter, rect(), this, client_.backgroundPalette( this, palette ) ); } + client_.renderWindowBorder( &painter, rect(), this, client_.backgroundPalette( this, palette ) ); // separator if( client_.drawSeparator() ) @@ -199,14 +191,20 @@ namespace Oxygen } // translate buttons up if window maximized - if( client_.compositingActive() && !client_.isMaximized() ) painter.translate( 0, -1 ); + if( + client_.compositingActive() && + !( client_.isMaximized() || type_ == ButtonItemClose || type_ == ButtonItemMenu ) ) + { painter.translate( 0, -1 ); } // base button color - QColor bt = palette.window().color(); + QColor bt = ((type_ == ButtonItemClose && forceInactive_ ) ? client_.backgroundPalette( this, palette ):palette).window().color(); // button icon and glow color depending on timeline state - color = buttonDetailColor(palette); - QColor glow = (type_ == ButtonClose) ? + color = (type_ == ButtonItemClose && forceInactive_ ) ? + buttonDetailColor( client_.backgroundPalette( this, palette ) ): + buttonDetailColor( palette ); + + QColor glow = (type_ == ButtonClose || type_ == ButtonItemClose ) ? KColorScheme(palette.currentColorGroup()).foreground(KColorScheme::NegativeText).color(): KColorScheme(palette.currentColorGroup()).decoration(KColorScheme::HoverColor).color(); glow = helper_.calcDarkColor( glow ); @@ -215,7 +213,7 @@ namespace Oxygen else if( status_ == Oxygen::Hovered ) color = glow; // button decoration - if( ( renderFlags_ & Deco ) && (type_ != ButtonMenu) ) + if( type_ != ButtonMenu && type_ != ButtonItemClose && type_ != ButtonItemMenu ) { // draw glow on hover @@ -244,32 +242,27 @@ namespace Oxygen } // Icon - if( renderFlags_ & Icon ) + // for menu button the application icon is used + if( type_ == ButtonMenu || type_ == ButtonItemMenu ) { - // for menu button the application icon is used - if (type_ == ButtonMenu) - { + const QPixmap& pixmap( client_.icon().pixmap( client_.configuration().iconScale() ) ); + double offset = 0.5*(width()-pixmap.width() ); + painter.drawPixmap(offset, offset-1, pixmap ); - const QPixmap& pixmap( client_.icon().pixmap( client_.configuration().iconScale() ) ); - double offset = 0.5*(width()-pixmap.width() ); - painter.drawPixmap(offset, offset-1, pixmap ); + } else { - } else { + painter.setRenderHints(QPainter::Antialiasing); + qreal width( 1.2 ); - painter.setRenderHints(QPainter::Antialiasing); - qreal width( 1.2 ); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen( helper_.calcLightColor( bt ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + drawIcon(&painter, palette, type_); - painter.setBrush(Qt::NoBrush); - painter.setPen(QPen( helper_.calcLightColor( bt ), width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - drawIcon(&painter, palette, type_); - - painter.translate(0,-1.5); - painter.setBrush(Qt::NoBrush); - painter.setPen(QPen(color, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - drawIcon(&painter, palette, type_); - - } + painter.translate(0,-1.5); + painter.setBrush(Qt::NoBrush); + painter.setPen(QPen(color, width, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + drawIcon(&painter, palette, type_); } @@ -324,6 +317,7 @@ namespace Oxygen } break; + case ButtonItemClose: case ButtonClose: painter->drawLine(QPointF( 7.5,7.5), QPointF(13.5,13.5)); painter->drawLine(QPointF(13.5,7.5), QPointF( 7.5,13.5)); diff --git a/clients/oxygen/oxygenbutton.h b/clients/oxygen/oxygenbutton.h index b3eb0df026..cd42168731 100644 --- a/clients/oxygen/oxygenbutton.h +++ b/clients/oxygen/oxygenbutton.h @@ -52,24 +52,10 @@ namespace Oxygen public: - //! flags - enum RenderFlag - { - - Background = 1<<0, - Deco = 1<<1, - Icon = 1<<2, - All = Background|Deco|Icon - - }; - - Q_DECLARE_FLAGS(RenderFlags, RenderFlag) - //! constructor explicit OxygenButton(OxygenClient &parent, const QString &tip=NULL, - ButtonType type=ButtonHelp, - RenderFlags flags = All); + ButtonType type=ButtonHelp ); //! destructor ~OxygenButton(); @@ -130,14 +116,13 @@ namespace Oxygen protected slots: //! update + /*! for some reason calling "update()" directly does not work for buttons that + are created directly by the client */ void setDirty( void ) - { update(); } + { if( parentWidget() ) parentWidget()->update( geometry() ); } private: - //! flags - RenderFlags renderFlags_; - //! parent client const OxygenClient &client_; @@ -153,9 +138,6 @@ namespace Oxygen //! true if button should be forced inactive bool forceInactive_; - //! true if color cache is to be reseted - QColor cachedButtonDetailColor_; - //! timeline used for smooth transitions QTimeLine timeLine_; diff --git a/clients/oxygen/oxygenclient.cpp b/clients/oxygen/oxygenclient.cpp index ab6da2ccd2..5111b4fd62 100644 --- a/clients/oxygen/oxygenclient.cpp +++ b/clients/oxygen/oxygenclient.cpp @@ -30,8 +30,8 @@ #include "oxygen.h" #include "oxygenbutton.h" -#include "oxygenshadowcache.h" #include "oxygensizegrip.h" +#include "lib/tileset.h" #include #include @@ -53,7 +53,7 @@ namespace Oxygen { p->drawEllipse(QRectF(point.x()-diameter/2, point.y()-diameter/2, diameter, diameter)); } - + //_________________________________________________________ QColor reduceContrast(const QColor &c0, const QColor &c1, double t) { @@ -82,7 +82,6 @@ namespace Oxygen //___________________________________________ OxygenClient::OxygenClient(KDecorationBridge *b, OxygenFactory *f): KCommonDecorationUnstable(b, f), - colorCacheInvalid_(true), factory_( f ), sizeGrip_( 0 ), timeLine_( 200, this ), @@ -231,9 +230,6 @@ namespace Oxygen bool maximized( isMaximized() ); int frameBorder( configuration().frameBorder() ); - - // used to increase hit area on the sides of the widget - int extraBorder = (maximized && compositingActive()) ? 0 : EXTENDED_HITAREA; int buttonSize( configuration().buttonSize() ); switch (lm) @@ -268,7 +264,7 @@ namespace Oxygen } - return border + extraBorder; + return border; } case LM_TitleEdgeTop: @@ -277,17 +273,15 @@ namespace Oxygen if( !( respectWindowState && maximized )) { border = TFRAMESIZE; - if( configuration().drawTitleOutline() ) border += HFRAMESIZE/2; } - return border + extraBorder; + return border; } case LM_TitleEdgeBottom: { - if( configuration().drawTitleOutline() ) return HFRAMESIZE/2; - else return 0; + return 0; } case LM_TitleEdgeLeft: @@ -297,7 +291,7 @@ namespace Oxygen if( !(respectWindowState && maximized) ) { border = 6; } - return border + extraBorder; + return border; } @@ -305,7 +299,11 @@ namespace Oxygen case LM_TitleBorderRight: { int border = 5; - if( configuration().drawTitleOutline() ) border += 2*HFRAMESIZE; + + // if title outline is to be drawn, one adds the space needed to + // separate title and tab border. namely the same value + if( configuration().drawTitleOutline() ) border += border; + return border; } @@ -313,15 +311,7 @@ namespace Oxygen case LM_ButtonHeight: case LM_TitleHeight: { - if (respectWindowState && isToolWindow()) { - - return buttonSize; - - } else { - - return buttonSize; - - } + return buttonSize; } case LM_ButtonSpacing: @@ -335,7 +325,7 @@ namespace Oxygen case LM_OuterPaddingRight: case LM_OuterPaddingTop: case LM_OuterPaddingBottom: - return shadowCache().shadowSize() - extraBorder; + return shadowCache().shadowSize(); default: return KCommonDecoration::layoutMetric(lm, respectWindowState, btn); @@ -344,48 +334,21 @@ namespace Oxygen } //_________________________________________________________ - QRect OxygenClient::titleRect( const QRect& frame ) const + QRect OxygenClient::titleBoundingRect( QPainter* painter, const QRect& rect, const QString& caption ) const { - int extraBorder = ( isMaximized() && compositingActive() ) ? 0 : EXTENDED_HITAREA; - - // dimensions - const int titleHeight = layoutMetric(LM_TitleHeight); - const int titleTop = layoutMetric(LM_TitleEdgeTop) + frame.top() - extraBorder; - const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft); - const int marginLeft = layoutMetric(LM_TitleBorderLeft); - const int marginRight = layoutMetric(LM_TitleBorderRight); - - const int titleLeft = frame.left() + titleEdgeLeft + buttonsLeftWidth() + marginLeft; - const int titleWidth = frame.width() - - titleEdgeLeft - layoutMetric(LM_TitleEdgeRight) - - buttonsLeftWidth() - buttonsRightWidth() - - marginLeft - marginRight; - - // maximum rect allocated for title - return QRect( titleLeft, titleTop-1, titleWidth, titleHeight ); - - } - - //_________________________________________________________ - QRect OxygenClient::titleBoundingRect( QPainter* painter, const QRect& frame, const QString& caption ) const - { - - QRect titleRect( OxygenClient::titleRect( frame ) ); - // get title bounding rect - QRect boundingRect = painter->boundingRect( titleRect, configuration().titleAlignment() | Qt::AlignVCenter, caption ); + QRect boundingRect = painter->boundingRect( rect, configuration().titleAlignment() | Qt::AlignVCenter, caption ); // adjust to make sure bounding rect // 1/ has same vertical alignment as original titleRect // 2/ does not exceeds available horizontal space - boundingRect.setTop( titleRect.top() ); - boundingRect.setBottom( titleRect.bottom() ); - boundingRect.setLeft( qMax( boundingRect.left(), titleRect.left() ) ); - boundingRect.setRight( qMin( boundingRect.right(), titleRect.right() ) ); + boundingRect.setTop( rect.top() ); + boundingRect.setBottom( rect.bottom() ); + + if( rect.left() > boundingRect.left() ) { boundingRect.setLeft( rect.left() ); } + if( rect.right() < boundingRect.right() ) { boundingRect.setRight( rect.right() ); } - // finally translate one pixel up - if( compositingActive() && !isMaximized() ) boundingRect.translate(0, -1 ); return boundingRect; } @@ -404,30 +367,18 @@ namespace Oxygen QColor OxygenClient::titlebarTextColor(const QPalette &palette, bool active) { - if( configuration().drawTitleOutline() ) - { - - return options()->color(ColorFont, active); - - } else if( active ){ + if( active ){ return palette.color(QPalette::Active, QPalette::WindowText); } else { - if(colorCacheInvalid_) - { - - QColor ab = palette.color(QPalette::Active, QPalette::Window); - QColor af = palette.color(QPalette::Active, QPalette::WindowText); - QColor nb = palette.color(QPalette::Inactive, QPalette::Window); - QColor nf = palette.color(QPalette::Inactive, QPalette::WindowText); - - colorCacheInvalid_ = false; - cachedTitlebarTextColor_ = reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); - } - - return cachedTitlebarTextColor_; + // todo: reimplement cache + QColor ab = palette.color(QPalette::Active, QPalette::Window); + QColor af = palette.color(QPalette::Active, QPalette::WindowText); + QColor nb = palette.color(QPalette::Inactive, QPalette::Window); + QColor nf = palette.color(QPalette::Inactive, QPalette::WindowText); + return reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))); } @@ -454,17 +405,20 @@ namespace Oxygen } //_________________________________________________________ - void OxygenClient::renderWindowBorder( QPainter* painter, const QRect& clipRect, const QWidget* widget, const QPalette& palette, TileSet::Tiles tiles ) const + void OxygenClient::renderWindowBorder( QPainter* painter, const QRect& clipRect, const QWidget* widget, const QPalette& palette ) const { - const QWidget* window = (isPreview()) ? OxygenClient::widget() : widget->window(); + // check if outline is needed + if( !( isActive() && configuration().drawTitleOutline() ) ) return; // get coordinates relative to the client area // this is annoying. One could use mapTo if this was taking const QWidget* and not // const QWidget* as argument. + const QWidget* window = (isPreview()) ? OxygenClient::widget() : widget->window(); const QWidget* w = widget; QPoint position( 0, 0 ); - while ( w != window && !w->isWindow() && w != w->parentWidget() ) { + while ( w != window && !w->isWindow() && w != w->parentWidget() ) + { position += w->geometry().topLeft(); w = w->parentWidget(); } @@ -481,25 +435,41 @@ namespace Oxygen r.adjust( shadowSize, shadowSize, -shadowSize, -shadowSize ); r.adjust(0,0, 1, 1); - // mask and painting frame + // title height + int titleHeight( layoutMetric( LM_TitleEdgeTop ) + layoutMetric( LM_TitleEdgeBottom ) + layoutMetric( LM_TitleHeight ) ); + + // darker frame + { + + QPoint topLeft( r.topLeft()-position ); + QRect rect( topLeft, QSize( r.width(), titleHeight ) ); + renderWindowBackground(painter, rect, widget, palette ); + + } + + // horizontal lina + { + int shadowSize = 7; + int height = shadowSize-3; + + QPoint topLeft( r.topLeft()+QPoint(0,titleHeight-height)-position ); + QRect rect( topLeft, QSize( r.width(), height ) ); + + // adjustements to cope with shadow size and outline border. + rect.adjust( -shadowSize, 0, shadowSize-1, 0 ); + if( configuration().frameBorder() > OxygenConfiguration::BorderTiny && configuration().drawTitleOutline() && isActive() && !isMaximized() ) + { rect.adjust( HFRAMESIZE-1, 0, -HFRAMESIZE+1, 0 ); } + + helper().slab( widget->palette().color( QPalette::Window ), 0, shadowSize ) + ->render( rect, painter, TileSet::Top ); + + } + QRegion mask; QRect frame; - // top line - if( tiles&TileSet::Top ) - { - int shadowSize = 5; - if( timeLineIsRunning() ) shadowSize*=opacity(); - - int height = HFRAMESIZE-1; - QRect rect( r.topLeft()-position, QSize( r.width(), height ) ); - helper().slab( palette.color( widget->backgroundRole() ), 0, shadowSize )->render( rect.adjusted(-shadowSize-1, 0, shadowSize+1, 2 ), painter, TileSet::Bottom ); - mask += rect; - frame |= rect; - } - // bottom line - if( configuration().frameBorder() > OxygenConfiguration::BorderNone && (tiles&TileSet::Bottom) ) + if( configuration().drawTitleOutline() && configuration().frameBorder() > OxygenConfiguration::BorderNone ) { int height = qMin( (int) HFRAMESIZE, layoutMetric( LM_BorderBottom ) )-1; QColor shadow( helper().backgroundBottomColor( widget->palette().color( widget->backgroundRole() ) ) ); @@ -514,16 +484,15 @@ namespace Oxygen } // left and right - if( configuration().frameBorder() >= OxygenConfiguration::BorderTiny ) + if( configuration().drawTitleOutline() && configuration().frameBorder() >= OxygenConfiguration::BorderTiny ) { // left QColor shadow( helper().calcDarkColor( widget->palette().color( widget->backgroundRole() ) ) ); painter->setPen( shadow ); - if( tiles&TileSet::Left ) { int width = qMin( (int)HFRAMESIZE, layoutMetric( LM_BorderLeft ) )-1; - QRect rect( r.topLeft()-position, QSize( width, r.height() ) ); + QRect rect( r.topLeft()-position + QPoint( 0, titleHeight ), QSize( width, r.height()-titleHeight ) ); painter->drawLine( r.topLeft()-position-QPoint(width+1,HFRAMESIZE), r.bottomLeft()-position-QPoint(width+1,-HFRAMESIZE) ); mask += rect; @@ -531,10 +500,9 @@ namespace Oxygen } // right - if( tiles&TileSet::Right ) { int width = qMin( (int)HFRAMESIZE, layoutMetric( LM_BorderRight ) )-1; - QRect rect( r.topRight()-position-QPoint(width,0), QSize( width, r.height() ) ); + QRect rect( r.topRight()-position-QPoint(width, -titleHeight ), QSize( width, r.height() - titleHeight ) ); painter->drawLine( r.topRight()-position-QPoint(-width-1,HFRAMESIZE), r.bottomRight()-position-QPoint(-width-1,-HFRAMESIZE) ); mask += rect; @@ -584,21 +552,14 @@ namespace Oxygen QRect r = (isPreview()) ? OxygenClient::widget()->rect():window->rect(); qreal shadowSize( shadowCache().shadowSize() ); r.adjust( shadowSize, shadowSize, -shadowSize, -shadowSize ); - r.adjust(0,0, 1, 1); - - int extraBorder = ( isMaximized() && compositingActive() ) ? 0 : EXTENDED_HITAREA; // dimensions const int titleHeight = layoutMetric(LM_TitleHeight); - const int titleTop = layoutMetric(LM_TitleEdgeTop) + r.top() - extraBorder; - - // dimensions - int x,y,w,h; - r.getRect(&x, &y, &w, &h); + const int titleTop = layoutMetric(LM_TitleEdgeTop) + r.top(); QColor local( color ); if( timeLineIsRunning() ) local = helper().alphaColor( color, opacity() ); - helper().drawSeparator( painter, QRect(x, titleTop+titleHeight-1.5, w, 2).translated( -position ), local, Qt::Horizontal); + helper().drawSeparator( painter, QRect(r.top(), titleTop+titleHeight-1.5, r.width(), 2).translated( -position ), local, Qt::Horizontal); if (clipRect.isValid()) { painter->restore(); } @@ -608,56 +569,61 @@ namespace Oxygen void OxygenClient::renderTitleOutline( QPainter* painter, const QRect& rect, const QPalette& palette ) const { + // center (for active windows only) + { + painter->save(); + int offset = 2; + int voffset = 1; + QRect adjustedRect( rect.adjusted( offset, voffset, -offset, 1 ) ); + + // prepare painter mask + QRegion mask( adjustedRect.adjusted( 1, 0, -1, 0 ) ); + mask += adjustedRect.adjusted( 0, 1, 0, 0 ); + painter->setClipRegion( mask, Qt::IntersectClip ); + + // draw window background + renderWindowBackground(painter, adjustedRect, widget(), palette ); + painter->restore(); + } + // shadow - { - int shadowSize = 7; - if( timeLineIsRunning() ) shadowSize *= opacity(); - int voffset = -shadowSize; - if( !isMaximized() ) voffset += HFRAMESIZE; - helper().slab( palette.color( widget()->backgroundRole() ), 0, shadowSize )->render( rect.adjusted(0, voffset, 0, 0 ), painter, TileSet::Bottom|TileSet::Left|TileSet::Right ); - - } - - // center - { - int offset = 4; - if( timeLineIsRunning() ) offset *= opacity(); - - int voffset = isMaximized() ? 0:HFRAMESIZE; - renderWindowBackground(painter, rect.adjusted( offset, voffset, -offset, -offset ), widget(), palette ); - } + int shadowSize = 7; + int offset = -2; + int voffset = 5-shadowSize; + QRect adjustedRect( rect.adjusted(offset, voffset, -offset, shadowSize) ); + helper().slab( palette.color( widget()->backgroundRole() ), 0, shadowSize )->render( adjustedRect, painter, TileSet::Top|TileSet::Left|TileSet::Right ); } //_________________________________________________________ - void OxygenClient::renderTitleText( QPainter* painter, const QRect& rect, Qt::Alignment alignment, QColor color) const + void OxygenClient::renderTitleText( QPainter* painter, const QRect& rect, QColor color ) const { + if( titleTimeLineIsRunning() ) { - if( !oldCaption().isEmpty() ) - { - color.setAlphaF( 1.0 - titleOpacity() ); - painter->setPen( color ); - painter->drawText( rect, alignment, oldCaption() ); - } - - if( !caption().isEmpty() ) - { - color.setAlphaF( titleOpacity() ); - painter->setPen( color ); - painter->drawText( rect, alignment, caption() ); - } + if( !oldCaption().isEmpty() ) renderTitleText( painter, rect, oldCaption(), helper().alphaColor( color, 1.0 - titleOpacity() ) ); + if( !caption().isEmpty() ) renderTitleText( painter, rect, caption(), helper().alphaColor( color, titleOpacity() ) ); } else if( !caption().isEmpty() ) { - painter->setPen( color ); - painter->drawText( rect, alignment, caption() ); + renderTitleText( painter, rect, caption(), color ); } } + //_______________________________________________________________________ + void OxygenClient::renderTitleText( QPainter* painter, const QRect& rect, const QString& caption, const QColor& color ) const + { + + Qt::Alignment alignment( configuration().titleAlignment() | Qt::AlignVCenter ); + QString local( QFontMetrics( painter->font() ).elidedText( caption, Qt::ElideRight, rect.width() ) ); + painter->setPen( color ); + painter->drawText( rect, alignment, local ); + + } + //_______________________________________________________________________ void OxygenClient::renderFloatFrame( QPainter* painter, const QRect& frame, const QPalette& palette ) const { @@ -675,16 +641,6 @@ namespace Oxygen KDecoration::options()->color(ColorTitleBar) ); - } else if( drawTitleOutline() ) { - - // for small borders, use a frame that matches the titlebar only - QRect local( frame.topLeft(), QSize( frame.width(), HFRAMESIZE ) ); - helper().drawFloatFrame( - painter, local, backgroundPalette( widget(), palette ).color( widget()->backgroundRole() ), - false, isActive() && configuration().useOxygenShadows(), - KDecoration::options()->color(ColorTitleBar) - ); - } else { // for small borders, use a frame that matches the titlebar only @@ -701,7 +657,7 @@ namespace Oxygen // for shaded maximized windows adjust frame and draw the bottom part of it helper().drawFloatFrame( painter, frame.adjusted( -4, 0, 4, 0 ), backgroundPalette( widget(), palette ).color( widget()->backgroundRole() ), - !compositingActive(), isActive(), + !( compositingActive() || configuration().frameBorder() == OxygenConfiguration::BorderNone ), isActive(), KDecoration::options()->color(ColorTitleBar), TileSet::Bottom ); @@ -819,10 +775,13 @@ namespace Oxygen QColor activeColor( backgroundColor( widget, palette, true ) ); QColor mixed( KColorUtils::mix( inactiveColor, activeColor, opacity() ) ); palette.setColor( widget->window()->backgroundRole(), mixed ); + palette.setColor( QPalette::Button, mixed ); } else if( isActive() ) { - palette.setColor( widget->window()->backgroundRole(), options()->color( KDecorationDefines::ColorTitleBar, true ) ); + QColor color = options()->color( KDecorationDefines::ColorTitleBar, true ); + palette.setColor( widget->window()->backgroundRole(), color ); + palette.setColor( QPalette::Button, color ); } @@ -846,16 +805,8 @@ namespace Oxygen void OxygenClient::updateWindowShape() { - if(isMaximized() || compositingActive() ) - { - - clearMask(); - - } else { - - setMask( calcMask() ); - - } + if(isMaximized() || compositingActive() ) clearMask(); + else setMask( calcMask() ); } @@ -967,40 +918,49 @@ namespace Oxygen // window background renderWindowBackground( &painter, frame, widget(), palette ); - if( drawTitleOutline() ) - { - if( !isMaximized() ) renderWindowBorder( &painter, frame, widget(), backgroundPalette( widget(), palette ) ); - else if( isShade() ) renderWindowBorder( &painter, frame, widget(), backgroundPalette( widget(), palette ), TileSet::Bottom ); - } + renderWindowBorder( &painter, frame, widget(), backgroundPalette( widget(), palette ) ); // clipping - if( compositingActive() ) painter.setClipping(false); + if( compositingActive() ) + { + painter.setClipping(false); + frame.adjust(-1,-1, 1, 1); + } + + // adjust frame if there are shadows + { + painter.save(); + painter.setRenderHint(QPainter::Antialiasing); + + + // float frame + renderFloatFrame( &painter, frame, palette ); + + // clipping + if( compositingActive() ) painter.setClipping(false); + + // resize handles + renderDots( &painter, frame, QColor(0, 0, 0, 66) ); + painter.restore(); + } // title bounding rect painter.setFont( options()->font(isActive(), false) ); - QRect boundingRect( titleBoundingRect( &painter, frame, caption() ) ); + QRect boundingRect( titleBoundingRect( &painter, caption() ) ); + if( isActive() && configuration().drawTitleOutline() ) + { + renderTitleOutline( &painter, boundingRect.adjusted( + -layoutMetric( LM_TitleBorderLeft ), + -layoutMetric( LM_TitleEdgeTop ), + layoutMetric( LM_TitleBorderRight ), 0 ), palette ); + } - // title outline - if( drawTitleOutline() ) - { renderTitleOutline( &painter, boundingRect.adjusted( -2*HFRAMESIZE, -layoutMetric(LM_TitleEdgeTop)+1, 2*HFRAMESIZE, 2 ), backgroundPalette( widget(), palette ) ); } - - // draw title text - renderTitleText( &painter, boundingRect, configuration().titleAlignment() | Qt::AlignVCenter, titlebarTextColor( backgroundPalette( widget(), palette ) ) ); + // title text + renderTitleText( &painter, boundingRect, titlebarTextColor( backgroundPalette( widget(), palette ) ) ); // separator if( drawSeparator() ) renderSeparator(&painter, frame, widget(), color ); - painter.setRenderHint(QPainter::Antialiasing); - - // adjust if there are shadows - if( compositingActive() ) frame.adjust(-1,-1, 1, 1); - - // float frame - renderFloatFrame( &painter, frame, palette ); - - //! dots - renderDots( &painter, frame, QColor(0, 0, 0, 66)); - } //_________________________________________________________________ diff --git a/clients/oxygen/oxygenclient.h b/clients/oxygen/oxygenclient.h index e868d0ef0c..10605a8973 100644 --- a/clients/oxygen/oxygenclient.h +++ b/clients/oxygen/oxygenclient.h @@ -34,8 +34,6 @@ #include "oxygen.h" #include "oxygenconfiguration.h" #include "lib/helper.h" -#include "lib/tileset.h" - namespace Oxygen { @@ -74,21 +72,13 @@ namespace Oxygen bool timeLineIsRunning( void ) const { return timeLine_.state() == QTimeLine::Running; } - //! true when title outline is to be drawn - bool drawTitleOutline( void ) const - { - return - ( timeLineIsRunning() || isActive() ) && - configuration().drawTitleOutline(); - } - //! true when separator is to be drawn bool drawSeparator( void ) const { - return - ( timeLineIsRunning() || isActive() ) && - configuration().drawSeparator() && - !configuration().drawTitleOutline(); + return + ( timeLineIsRunning() || isActive() ) && + configuration().drawSeparator() && + !configuration().drawTitleOutline(); } //@} @@ -121,9 +111,9 @@ namespace Oxygen //! return animation opacity qreal opacity( void ) const { - int frame( timeLine_.currentFrame() ); - if( timeLine_.direction() == QTimeLine::Backward ) frame -= timeLine_.startFrame(); - return qreal( frame )/qreal( timeLine_.endFrame() ); + int frame( timeLine_.currentFrame() ); + if( timeLine_.direction() == QTimeLine::Backward ) frame -= timeLine_.startFrame(); + return qreal( frame )/qreal( timeLine_.endFrame() ); } //!@name metrics and color definitions @@ -132,8 +122,9 @@ namespace Oxygen //! dimensions virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const; - //! get maximum space available for title - virtual QRect titleRect( const QRect& ) const; + //! get title bounding rect + virtual QRect titleBoundingRect( QPainter* painter, const QString& caption ) const + { return titleBoundingRect( painter, titleRect(), caption ); } //! get title bounding rect virtual QRect titleBoundingRect( QPainter*, const QRect&, const QString& ) const; @@ -158,7 +149,7 @@ namespace Oxygen //! window border // this draws a "blue" border around active window - virtual void renderWindowBorder( QPainter*, const QRect&, const QWidget*, const QPalette&, TileSet::Tiles tiles = TileSet::Ring ) const; + virtual void renderWindowBorder( QPainter*, const QRect&, const QWidget*, const QPalette& ) const; //! separator virtual void renderSeparator( QPainter*, const QRect&, const QWidget*, const QColor& ) const; @@ -167,7 +158,10 @@ namespace Oxygen virtual void renderTitleOutline( QPainter*, const QRect&, const QPalette& ) const; //! title text - virtual void renderTitleText( QPainter*, const QRect&, Qt::Alignment, QColor ) const; + virtual void renderTitleText( QPainter*, const QRect&, QColor ) const; + + //! title text + virtual void renderTitleText( QPainter*, const QRect&, const QString&, const QColor& ) const; //! render float frame virtual void renderFloatFrame( QPainter*, const QRect&, const QPalette& ) const; @@ -202,15 +196,7 @@ namespace Oxygen protected: //! paint - void paintEvent( QPaintEvent* ); - - protected slots: - - //! update old caption with current - void updateOldCaption( void ) - { setOldCaption( caption() ); } - - private: + virtual void paintEvent( QPaintEvent* ); //! title timeline bool titleTimeLineIsRunning( void ) const @@ -235,10 +221,10 @@ namespace Oxygen //! return true when activity change are animated bool animateTitleChange( void ) const { - return - configuration().useAnimations() && - !configuration().drawTitleOutline() && - !isPreview(); + return + configuration().useAnimations() && + !configuration().drawTitleOutline() && + !isPreview(); } //! calculate mask @@ -269,14 +255,13 @@ namespace Oxygen //@} - //! configuration - OxygenConfiguration configuration_; + protected slots: - //! used to invalidate color cache - bool colorCacheInvalid_; + //! update old caption with current + void updateOldCaption( void ) + { setOldCaption( caption() ); } - //! stored color - QColor cachedTitlebarTextColor_; + private: //! factory OxygenFactory* factory_; @@ -284,6 +269,9 @@ namespace Oxygen //! size grip widget OxygenSizeGrip* sizeGrip_; + //! configuration + OxygenConfiguration configuration_; + //! animation timeLine QTimeLine timeLine_; diff --git a/clients/oxygen/oxygenshadowcache.cpp b/clients/oxygen/oxygenshadowcache.cpp index cf32d9b82f..46c035871c 100644 --- a/clients/oxygen/oxygenshadowcache.cpp +++ b/clients/oxygen/oxygenshadowcache.cpp @@ -139,40 +139,7 @@ namespace Oxygen Key key( client ); QPalette palette( client->backgroundPalette( client->widget(), client->widget()->palette() ) ); QColor color( palette.color( client->widget()->backgroundRole() ) ); - - if( active && client->configuration().drawTitleOutline() && client->configuration().frameBorder() == OxygenConfiguration::BorderNone ) - { - - // a more complex tile set is needed for the configuration above: - // top corners must be beveled with the "active titlebar color" while - // bottom corners must be beveled with the "window background color". - // this requires generating two shadow pixmaps and tiling them in the tileSet. - - qreal size( shadowSize() ); - QPixmap shadow( 2*size, 2*size ); - shadow.fill( Qt::transparent ); - QPainter p( &shadow ); - p.setRenderHint( QPainter::Antialiasing ); - - QPixmap shadowTop = simpleShadowPixmap( color, key, active ); - QRect topRect( shadow.rect() ); - topRect.setBottom( int( size )-1 ); - p.setClipRect( topRect ); - p.drawPixmap( QPointF( 0, 0 ), shadowTop ); - - // get window color - palette = client->widget()->palette(); - color = palette.color( client->widget()->backgroundRole() ); - QPixmap shadowBottom = simpleShadowPixmap( color, key, active ); - QRect bottomRect( shadow.rect() ); - bottomRect.setTop( int( size ) ); - p.setClipRect( bottomRect ); - p.drawPixmap( QPointF( 0, 0 ), shadowBottom ); - p.end(); - - return shadow; - - } else return simpleShadowPixmap( color, key, active ); + return simpleShadowPixmap( color, key, active ); } @@ -202,8 +169,8 @@ namespace Oxygen qreal hoffset = shadowConfiguration.horizontalOffset()*shadowSize/fixedSize; qreal voffset = shadowConfiguration.verticalOffset()*shadowSize/fixedSize; - // some gradients rendering are different at bottom corners for NoBorders windows - bool noBorder( key.frameBorder == Key::BorderNone && !key.isShade ); + // some gradients rendering are different at bottom corners if client has no border + bool hasBorder( key.hasBorder || key.isShade ); if( active && key.useOxygenShadows ) { @@ -220,7 +187,7 @@ namespace Oxygen { c.setAlpha( values[i] ); rg.setColorAt( x[i], c ); } p.setBrush( rg ); - renderGradient( p, shadow.rect(), rg, noBorder ); + renderGradient( p, shadow.rect(), rg, hasBorder ); } @@ -252,7 +219,7 @@ namespace Oxygen for( int i = 0; iconfiguration().useOxygenShadows(); isShade = client->isShade(); hasTitleOutline = client->configuration().drawTitleOutline(); - switch( client->configuration().frameBorder() ) - { - case OxygenConfiguration::BorderNone: frameBorder = Key::BorderNone; break; - case OxygenConfiguration::BorderNoSide: frameBorder = Key::BorderNoSide; break; - default: frameBorder = Key::BorderAny; break; - } + hasBorder = ( client->configuration().frameBorder() > OxygenConfiguration::BorderNone ); } diff --git a/clients/oxygen/oxygenshadowcache.h b/clients/oxygen/oxygenshadowcache.h index bb96229ff5..b5dee22ebd 100644 --- a/clients/oxygen/oxygenshadowcache.h +++ b/clients/oxygen/oxygenshadowcache.h @@ -88,14 +88,6 @@ namespace Oxygen public: - //! this is a shorter enumeration - enum FrameBorder - { - BorderNone, - BorderNoSide, - BorderAny - }; - //! explicit constructor explicit Key( void ): index(0), @@ -103,7 +95,7 @@ namespace Oxygen useOxygenShadows(false), isShade(false), hasTitleOutline(false), - frameBorder( BorderAny ) + hasBorder( true ) {} //! constructor from client @@ -111,12 +103,12 @@ namespace Oxygen //! constructor from int Key( int hash ): - index( hash>>6 ), - active( (hash>>5)&1 ), - useOxygenShadows( (hash>>4)&1 ), - isShade( (hash>>3)&1 ), - hasTitleOutline( (hash>>2)&1 ), - frameBorder( (FrameBorder)(hash&3) ) + index( hash>>5 ), + active( (hash>>4)&1 ), + useOxygenShadows( (hash>>3)&1 ), + isShade( (hash>>2)&1 ), + hasTitleOutline( (hash>>1)&1 ), + hasBorder( hash&1 ) {} //! hash function @@ -126,12 +118,12 @@ namespace Oxygen // note this can be optimized because not all of the flag configurations are actually relevant // allocate 3 empty bits for flags return - ( index << 6 ) | - ( active << 5 ) | - (useOxygenShadows << 4 ) | - (isShade<<3) | - (hasTitleOutline<<2) | - (frameBorder<<0); + ( index << 5 ) | + ( active << 4 ) | + (useOxygenShadows << 3 ) | + (isShade<<2) | + (hasTitleOutline<<1) | + (hasBorder<<0); } @@ -140,8 +132,7 @@ namespace Oxygen bool useOxygenShadows; bool isShade; bool hasTitleOutline; - - FrameBorder frameBorder; + bool hasBorder; }; @@ -164,7 +155,7 @@ namespace Oxygen //! draw gradient into rect /*! a separate method is used in order to properly account for corners */ - void renderGradient( QPainter&, const QRectF&, const QRadialGradient&, bool noBorder = false ) const; + void renderGradient( QPainter&, const QRectF&, const QRadialGradient&, bool hasBorder = true ) const; //! helper OxygenHelper& helper_;