kde-workspace/libs/oxygen/oxygenhelper.h

442 lines
14 KiB
C++

#ifndef OXYGEN_HELPER_H
#define OXYGEN_HELPER_H
/*
* Copyright 2009-2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
* Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com>
* Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
* Copyright 2007 Casper Boemann <cbr@boemann.dk>
* Copyright 2007 Fredrik Höglund <fredrik@kde.org>
*
* 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 <KSharedConfig>
#include <KComponentData>
#include <KColorScheme>
#include <QtGui/QColor>
#include <QtGui/QPixmap>
#include <QtGui/QWidget>
#include <QtGui/qbrush.h>
#include <QtCore/QCache>
#ifdef Q_WS_X11
#include <X11/Xdefs.h>
#endif
namespace Oxygen
{
template<typename T> class BaseCache: public QCache<quint64, T>
{
public:
//! constructor
BaseCache( int maxCost ):
QCache<quint64, T>( 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<quint64, T>::object( key ) : 0; }
//! max cost
void setMaxCost( int cost )
{
if( cost <= 0 ) {
QCache<quint64, T>::clear();
QCache<quint64, T>::setMaxCost( 1 );
setEnabled( false );
} else {
setEnabled( true );
QCache<quint64, T>::setMaxCost( cost );
}
}
private:
//! enable flag
bool _enabled;
};
template<typename T> class Cache
{
public:
//! constructor
Cache()
{}
//! destructor
~Cache()
{}
//! return cache matching a given key
//typedef QCache<quint64, T> Value;
typedef BaseCache<T> 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<Value> 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 );
//! background pixmap
bool hasBackgroundPixmap( void ) const
{ return !_backgroundPixmap.isNull(); }
//! background pixmap
void setBackgroundPixmap( const QPixmap& pixmap )
{ _backgroundPixmap = pixmap; }
//! offset
void setBackgroundPixmapOffset( const QPoint& offset )
{ _backgroundPixmapOffset = offset; }
//! render window background using a given color as a reference
virtual void renderBackgroundPixmap( QPainter* p, const QRect& clipRect, const QWidget* widget, const QWidget* window, 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;
//! set background pixmap hint to widget
virtual void setHasBackgroundPixmap( WId, bool ) const;
//! true if background pixmap hint is set
virtual bool hasBackgroundPixmap( 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<QColor> ColorCache;
//! shortcut to pixmap cache
typedef BaseCache<QPixmap> PixmapCache;
private:
//!@name tileset caches
//!@{
//! slabs
Oxygen::Cache<TileSet> _slabCache;
//! sunken slabs
BaseCache<TileSet> _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<quint32, bool> ColorMap;
ColorMap _highThreshold;
ColorMap _lowThreshold;
//! background pixmap
QPixmap _backgroundPixmap;
//! background pixmap offsets
QPoint _backgroundPixmapOffset;
#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;
//! background gradient hint atom
Atom _backgroundPixmapAtom;
#endif
};
}
#endif