#ifndef OXYGEN_HELPER_H #define OXYGEN_HELPER_H /* * Copyright 2009-2010 Hugo Pereira Da Costa * Copyright 2008 Long Huynh Huu * Copyright 2007 Matthew Woehlke * Copyright 2007 Casper Boemann * Copyright 2007 Fredrik Höglund * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "oxygentileset.h" #include #include #include #include #include #include #include #include #ifdef Q_WS_X11 #include #endif namespace Oxygen { template class BaseCache: public QCache { public: //! constructor BaseCache( int maxCost ): QCache( maxCost ), _enabled( true ) {} //! constructor explicit BaseCache( void ): _enabled( true ) {} //! destructor ~BaseCache( void ) {} //! enable void setEnabled( bool value ) { _enabled = value; } //! enable state bool enabled( void ) const { return _enabled; } //! access T* object( const quint64& key ) { return _enabled ? QCache::object( key ) : 0; } //! max cost void setMaxCost( int cost ) { if( cost <= 0 ) { QCache::clear(); QCache::setMaxCost( 1 ); setEnabled( false ); } else { setEnabled( true ); QCache::setMaxCost( cost ); } } private: //! enable flag bool _enabled; }; template class Cache { public: //! constructor Cache() {} //! destructor ~Cache() {} //! return cache matching a given key //typedef QCache Value; typedef BaseCache Value; Value* get( const QColor& color ) { const quint64 key = ( color.isValid() ? color.rgba():0 ); Value* cache = data_.object( key ); if ( !cache ) { cache = new Value( data_.maxCost() ); data_.insert( key, cache ); } return cache; } //! clear void clear( void ) { data_.clear(); } //! max cache size void setMaxCacheSize( int value ) { data_.setMaxCost( value ); foreach( quint64 key, data_.keys() ) { data_.object( key )->setMaxCost( value ); } } private: //! data BaseCache data_; }; //! oxygen style helper class. /*! contains utility functions used at multiple places in both oxygen style and oxygen window decoration */ class OXYGEN_EXPORT Helper { public: //! constructor explicit Helper( const QByteArray& componentName ); //! destructor virtual ~Helper() {} //! reload configuration virtual void reloadConfig(); //! pointer to shared config KSharedConfigPtr config() const; //! reset all caches virtual void invalidateCaches(); //! update maximum cache size virtual void setMaxCacheSize( int ); //!@name window background gradients //@{ /*! \par y_shift: shift the background gradient upwards, to fit with the windec \par gradientHeight: the height of the generated gradient. for different heights, the gradient is translated so that it is always at the same position from the bottom */ virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QPalette& pal, int y_shift=-23, int gradientHeight = 20 ) { renderWindowBackground( p, clipRect, widget, pal.color( widget->window()->backgroundRole() ), y_shift, gradientHeight ); } /*! y_shift: shift the background gradient upwards, to fit with the windec gradientHeight: the height of the generated gradient. for different heights, the gradient is translated so that it is always at the same position from the bottom */ virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QPalette& pal, int y_shift=-23, int gradientHeight = 20 ) { renderWindowBackground( p, clipRect, widget, window, pal.color( window->backgroundRole() ), y_shift, gradientHeight ); } //! render window background using a given color as a reference virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QColor& color, int y_shift=-23, int gradientHeight = 20 ) { renderWindowBackground( p, clipRect, widget, widget->window(), color, y_shift, gradientHeight ); } //! render window background using a given color as a reference virtual void renderWindowBackground( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, const QColor& color, int y_shift=-23, int gradientHeight = 20 ); //@} //! dots void renderDot( QPainter*, const QPoint&, const QColor& ); //! returns true for too 'dark' colors bool lowThreshold( const QColor& color ); //! returns true for too 'light' colors bool highThreshold( const QColor& color ); //! add alpha channel multiplier to color static QColor alphaColor( QColor color, qreal alpha ); //! calculated light color from argument virtual const QColor& calcLightColor( const QColor& color ); //! calculated dark color from argument virtual const QColor& calcDarkColor( const QColor& color ); //! calculated shadow color from argument virtual const QColor& calcShadowColor( const QColor& color ); //! returns menu background color matching position in a given top level widget virtual const QColor& backgroundColor( const QColor& color, const QWidget* w, const QPoint& point ) { if( !( w && w->window() ) || checkAutoFillBackground( w ) ) return color; else return backgroundColor( color, w->window()->height(), w->mapTo( w->window(), point ).y() ); } //! returns menu background color matching position in a top level widget of given height virtual const QColor& backgroundColor( const QColor& color, int height, int y ) { return backgroundColor( color, qMin( qreal( 1.0 ), qreal( y )/qMin( 300, 3*height/4 ) ) ); } //! color used for background radial gradient virtual const QColor& backgroundRadialColor( const QColor& color ); //! color used at the top of window background virtual const QColor& backgroundTopColor( const QColor& color ); //! color used at the bottom of window background virtual const QColor& backgroundBottomColor( const QColor& color ); //! vertical gradient for window background virtual QPixmap verticalGradient( const QColor& color, int height, int offset = 0 ); //! radial gradient for window background virtual QPixmap radialGradient( const QColor& color, int width, int height = 20 ); //! merge background and front color for check marks, arrows, etc. using _contrast virtual const QColor& decoColor( const QColor& background, const QColor& color ); //! returns a region matching given rect, with rounded corners, based on the multipliers /*! setting any of the multipliers to zero will result in no corners shown on the corresponding side */ virtual QRegion roundedMask( const QRect&, int left = 1, int right = 1, int top = 1, int bottom = 1 ) const; //! draw frame that mimics some sort of shadows around a panel /*! it is used for menus, detached dock panels and toolbar, as well as window decoration when compositing is disabled */ virtual void drawFloatFrame( QPainter* p, const QRect r, const QColor& color, bool drawUglyShadow=true, bool isActive=false, const QColor& frameColor=QColor(), TileSet::Tiles tiles = TileSet::Ring ); //! draw dividing line virtual void drawSeparator( QPainter*, const QRect&, const QColor&, Qt::Orientation ); //! default slab virtual TileSet* slab( const QColor& color, qreal shade, int size = 7 ) { return slab( color, QColor(), shade, size ); } //! default slab (with glow) virtual TileSet* slab( const QColor&, const QColor& glow, qreal shade, int size = 7 ); //! sunken slab virtual TileSet *slabSunken( const QColor&, int size = 7 ); //! fill a slab of given size with brush set on painter void fillSlab( QPainter&, const QRect&, int size = 7 ) const; //! linear gradient used to fill buttons virtual void fillButtonSlab( QPainter&, const QRect&, const QColor&, bool sunken ); //! inverse (inner-hole) shadow /*! this method must be public because it is used directly by OxygenStyle to draw dials */ void drawInverseShadow( QPainter&, const QColor&, int pad, int size, qreal fuzz ) const; //! focus brush const KStatefulBrush& viewFocusBrush( void ) const { return _viewFocusBrush; } //! hover brush const KStatefulBrush& viewHoverBrush( void ) const { return _viewHoverBrush; } //! negative text brush ( used for close button hover ) const KStatefulBrush& viewNegativeTextBrush( void ) const { return _viewNegativeTextBrush; } /*! returns first widget in parent chain that sets autoFillBackground to true, or NULL if none */ const QWidget* checkAutoFillBackground( const QWidget* ) const; //!@name background gradient XProperty //@{ //! set background gradient hint to widget virtual void setHasBackgroundGradient( WId, bool ) const; //! true if background gradient hint is set virtual bool hasBackgroundGradient( WId ) const; //@} protected: //! return color key for a given color, properly accounting for invalid colors quint64 colorKey( const QColor& color ) const { return color.isValid() ? color.rgba():0; } //! generic slab painting (to be stored in tilesets) virtual void drawSlab( QPainter&, const QColor&, qreal shade ); //! generic outer shadow (to be stored in tilesets) virtual void drawShadow( QPainter&, const QColor&, int size ); //! generic outer glow (to be stored in tilesets) virtual void drawOuterGlow( QPainter&, const QColor&, int size ); //! return background adjusted color matching relative vertical position in window const QColor& backgroundColor( const QColor&, qreal ratio ); //!@name global configuration parameters //@{ static const qreal _glowBias; static const qreal _slabThickness; static const qreal _shadowGain; qreal _contrast; //@} //! shortcut to color caches /*! it is made protected because it is also used in the style helper */ typedef BaseCache ColorCache; //! shortcut to pixmap cache typedef BaseCache PixmapCache; private: //!@name tileset caches //!@{ //! slabs Oxygen::Cache _slabCache; //! sunken slabs BaseCache _slabSunkenCache; //@} //!@name brushes //@{ KStatefulBrush _viewFocusBrush; KStatefulBrush _viewHoverBrush; KStatefulBrush _viewNegativeTextBrush; //@} KComponentData _componentData; KSharedConfigPtr _config; qreal _bgcontrast; //!@name color caches //@{ ColorCache _decoColorCache; ColorCache _lightColorCache; ColorCache _darkColorCache; ColorCache _shadowColorCache; ColorCache _backgroundTopColorCache; ColorCache _backgroundBottomColorCache; ColorCache _backgroundRadialColorCache; ColorCache _backgroundColorCache; //@} PixmapCache _backgroundCache; PixmapCache _dotCache; //! high threshold colors typedef QMap ColorMap; ColorMap _highThreshold; ColorMap _lowThreshold; #ifdef Q_WS_X11 //! set value for given hint void setHasHint( WId, Atom, bool ) const; //! value for given hint bool hasHint( WId, Atom ) const; //! background gradient hint atom Atom _backgroundGradientAtom; #endif }; } #endif